29 using System.Collections.Generic;
30 using System.Collections.Specialized;
31 using System.Reflection;
36 using OpenMetaverse.StructuredData;
37 using OpenSim.Framework;
38 using OpenSim.Region.Framework.Interfaces;
39 using OpenSim.Region.Framework.Scenes;
40 using OpenSim.Services.Interfaces;
43 namespace OpenSim.Services.Connectors.SimianGrid
65 [Extension(Path =
"/OpenSim/RegionModules", NodeName =
"RegionModule", Id =
"SimianInventoryServiceConnector")]
68 private static readonly ILog m_log =
70 MethodBase.GetCurrentMethod().DeclaringType);
72 private string m_serverUrl = String.Empty;
73 private string m_userServerUrl = String.Empty;
75 private bool m_Enabled =
false;
77 private const double CACHE_EXPIRATION_SECONDS = 20.0;
78 private static ExpiringCache<UUID, InventoryItemBase> m_ItemCache;
80 #region ISharedRegionModule
82 public Type ReplaceableInterface {
get {
return null; } }
88 public string Name {
get {
return "SimianInventoryServiceConnector"; } }
92 #endregion ISharedRegionModule
101 if (!url.EndsWith(
"/") && !url.EndsWith(
"="))
105 if (m_ItemCache == null)
106 m_ItemCache =
new ExpiringCache<UUID, InventoryItemBase>();
112 IConfig moduleConfig = source.Configs[
"Modules"];
113 if (moduleConfig != null)
115 string name = moduleConfig.GetString(
"InventoryServices",
"");
121 private void CommonInit(IConfigSource source)
123 IConfig gridConfig = source.Configs[
"InventoryService"];
124 if (gridConfig != null)
126 string serviceUrl = gridConfig.GetString(
"InventoryServerURI");
127 if (!
String.IsNullOrEmpty(serviceUrl))
129 if (!serviceUrl.EndsWith(
"/") && !serviceUrl.EndsWith(
"="))
130 serviceUrl = serviceUrl +
'/';
131 m_serverUrl = serviceUrl;
133 gridConfig = source.Configs[
"UserAccountService"];
134 if (gridConfig != null)
136 serviceUrl = gridConfig.GetString(
"UserAccountServerURI");
137 if (!
String.IsNullOrEmpty(serviceUrl))
139 m_userServerUrl = serviceUrl;
141 if (m_ItemCache == null)
142 m_ItemCache =
new ExpiringCache<UUID, InventoryItemBase>();
148 if (
String.IsNullOrEmpty(m_serverUrl))
149 m_log.Info(
"[SIMIAN INVENTORY CONNECTOR]: No InventoryServerURI specified, disabling connector");
150 else if (
String.IsNullOrEmpty(m_userServerUrl))
151 m_log.Info(
"[SIMIAN INVENTORY CONNECTOR]: No UserAccountServerURI specified, disabling connector");
161 NameValueCollection requestArgs =
new NameValueCollection
163 {
"RequestMethod",
"AddInventory" },
164 {
"OwnerID", userID.ToString() }
167 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
168 bool success = response[
"Success"].AsBoolean();
171 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Inventory creation for " + userID +
" failed: " + response[
"Message"].AsString());
183 NameValueCollection requestArgs =
new NameValueCollection
185 {
"RequestMethod",
"GetInventoryNode" },
186 {
"ItemID", userID.ToString() },
187 {
"OwnerID", userID.ToString() },
188 {
"IncludeFolders",
"1" },
189 {
"IncludeItems",
"0" },
190 {
"ChildrenOnly",
"0" }
193 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
194 if (response[
"Success"].AsBoolean() && response[
"Items"] is
OSDArray)
197 return GetFoldersFromResponse(items, userID,
true);
201 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Failed to retrieve inventory skeleton for " + userID +
": " +
202 response[
"Message"].AsString());
203 return new List<InventoryFolderBase>(0);
214 NameValueCollection requestArgs =
new NameValueCollection
216 {
"RequestMethod",
"GetInventoryNode" },
217 {
"ItemID", userID.ToString() },
218 {
"OwnerID", userID.ToString() },
219 {
"IncludeFolders",
"1" },
220 {
"IncludeItems",
"0" },
221 {
"ChildrenOnly",
"1" }
224 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
225 if (response[
"Success"].AsBoolean() && response[
"Items"] is
OSDArray)
228 List<InventoryFolderBase> folders = GetFoldersFromResponse(items, userID,
true);
230 if (folders.Count > 0)
245 string contentType = SLUtil.SLAssetTypeToContentType((int)type);
247 NameValueCollection requestArgs =
new NameValueCollection
249 {
"RequestMethod",
"GetFolderForType" },
250 {
"ContentType", contentType },
251 {
"OwnerID", userID.ToString() }
254 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
255 if (response[
"Success"].AsBoolean() && response[
"Folder"] is
OSDMap)
260 folder[
"ID"].AsUUID(),
261 folder[
"Name"].AsString(),
262 folder[
"OwnerID"].AsUUID(),
263 (
short)SLUtil.ContentTypeToSLAssetType(folder[
"ContentType"].AsString()),
264 folder[
"ParentID"].AsUUID(),
265 (ushort)folder[
"Version"].AsInteger()
270 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Default folder not found for content type " + contentType +
": " + response[
"Message"].AsString());
271 return GetRootFolder(userID);
283 if (m_ItemCache.TryGetValue(item.
ID, out retrieved))
286 NameValueCollection requestArgs =
new NameValueCollection
288 {
"RequestMethod",
"GetInventoryNode" },
289 {
"ItemID", item.ID.ToString() },
290 {
"OwnerID", item.Owner.ToString() },
291 {
"IncludeFolders",
"1" },
292 {
"IncludeItems",
"1" },
293 {
"ChildrenOnly",
"1" }
296 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
297 if (response[
"Success"].AsBoolean() && response[
"Items"] is
OSDArray)
299 List<InventoryItemBase> items = GetItemsFromResponse((
OSDArray)response[
"Items"]);
304 for (
int i = 0; i < items.Count; i++)
306 if (items[i].ID == item.
ID)
308 retrieved = items[i];
309 m_ItemCache.AddOrUpdate(item.ID, retrieved, CACHE_EXPIRATION_SECONDS);
316 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Item " + item.ID +
" owned by " + item.Owner +
" not found");
325 item.Owner = principalID;
326 foreach (
UUID id in itemIDs)
329 result[i++] = GetItem(item);
342 NameValueCollection requestArgs =
new NameValueCollection
344 {
"RequestMethod",
"GetInventoryNode" },
345 {
"ItemID", folder.ID.ToString() },
346 {
"OwnerID", folder.Owner.ToString() },
347 {
"IncludeFolders",
"1" },
348 {
"IncludeItems",
"0" },
349 {
"ChildrenOnly",
"1" }
352 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
353 if (response[
"Success"].AsBoolean() && response[
"Items"] is
OSDArray)
356 List<InventoryFolderBase> folders = GetFoldersFromResponse(items, folder.
ID,
true);
358 if (folders.Count > 0)
374 inventory.OwnerID = userID;
376 NameValueCollection requestArgs =
new NameValueCollection
378 {
"RequestMethod",
"GetInventoryNode" },
379 {
"ItemID", folderID.ToString() },
380 {
"OwnerID", userID.ToString() },
381 {
"IncludeFolders",
"1" },
382 {
"IncludeItems",
"1" },
383 {
"ChildrenOnly",
"1" }
386 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
387 if (response[
"Success"].AsBoolean() && response[
"Items"] is
OSDArray)
391 inventory.Folders = GetFoldersFromResponse(items, folderID,
false);
392 inventory.Items = GetItemsFromResponse(items);
396 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Error fetching folder " + folderID +
" content for " + userID +
": " +
397 response[
"Message"].AsString());
398 inventory.Folders =
new List<InventoryFolderBase>(0);
399 inventory.Items =
new List<InventoryItemBase>(0);
409 foreach (
UUID fid
in folderIDs)
411 invColl[i++] = GetFolderContent(principalID, fid);
426 inventory.OwnerID = userID;
428 NameValueCollection requestArgs =
new NameValueCollection
430 {
"RequestMethod",
"GetInventoryNode" },
431 {
"ItemID", folderID.ToString() },
432 {
"OwnerID", userID.ToString() },
433 {
"IncludeFolders",
"0" },
434 {
"IncludeItems",
"1" },
435 {
"ChildrenOnly",
"1" }
438 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
439 if (response[
"Success"].AsBoolean() && response[
"Items"] is
OSDArray)
442 return GetItemsFromResponse(items);
446 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Error fetching folder " + folderID +
" for " + userID +
": " +
447 response[
"Message"].AsString());
448 return new List<InventoryItemBase>(0);
459 NameValueCollection requestArgs =
new NameValueCollection
461 {
"RequestMethod",
"AddInventoryFolder" },
462 {
"FolderID", folder.ID.ToString() },
463 {
"ParentID", folder.ParentID.ToString() },
464 {
"OwnerID", folder.Owner.ToString() },
465 {
"Name", folder.Name },
466 {
"ContentType", SLUtil.SLAssetTypeToContentType(folder.Type) }
469 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
470 bool success = response[
"Success"].AsBoolean();
474 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Error creating folder " + folder.Name +
" for " + folder.Owner +
": " +
475 response[
"Message"].AsString());
488 return AddFolder(folder);
498 return AddFolder(folder);
509 return DeleteItems(userID, folderIDs);
520 bool allSuccess =
true;
522 for (
int i = 0; i < itemIDs.Count; i++)
524 UUID itemID = itemIDs[i];
526 NameValueCollection requestArgs =
new NameValueCollection
528 {
"RequestMethod",
"RemoveInventoryNode" },
529 {
"OwnerID", userID.ToString() },
530 {
"ItemID", itemID.ToString() }
533 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
534 bool success = response[
"Success"].AsBoolean();
538 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Error removing item " + itemID +
" for " + userID +
": " +
539 response[
"Message"].AsString());
554 NameValueCollection requestArgs =
new NameValueCollection
556 {
"RequestMethod",
"PurgeInventoryFolder" },
557 {
"OwnerID", folder.Owner.ToString() },
558 {
"FolderID", folder.ID.ToString() }
561 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
562 bool success = response[
"Success"].AsBoolean();
566 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Error purging folder " + folder.ID +
" for " + folder.Owner +
": " +
567 response[
"Message"].AsString());
584 if (Enum.IsDefined(typeof(FolderType), (sbyte)item.
AssetType))
585 folder = GetFolderForType(item.
Owner, (FolderType)item.AssetType);
586 if (folder != null && folder.
ID !=
UUID.Zero)
587 item.Folder = folder.ID;
589 item.Folder = item.Owner;
592 if ((AssetType)item.AssetType == AssetType.Gesture)
596 m_log.WarnFormat(
"[SIMIAN INVENTORY CONNECTOR]: Adding inventory item {0} ({1}) with no base permissions", item.Name, item.ID);
600 {
"BaseMask", OSD.FromInteger(item.BasePermissions) },
601 {
"EveryoneMask", OSD.FromInteger(item.EveryOnePermissions) },
602 {
"GroupMask", OSD.FromInteger(item.GroupPermissions) },
603 {
"NextOwnerMask", OSD.FromInteger(item.NextPermissions) },
604 {
"OwnerMask", OSD.FromInteger(item.CurrentPermissions) }
609 {
"Flags", OSD.FromInteger(item.Flags) },
610 {
"GroupID", OSD.FromUUID(item.GroupID) },
611 {
"GroupOwned", OSD.FromBoolean(item.GroupOwned) },
612 {
"SalePrice", OSD.FromInteger(item.SalePrice) },
613 {
"SaleType", OSD.FromInteger(item.SaleType) },
614 {
"Permissions", permissions }
619 string invContentType = SLUtil.SLInvTypeToContentType(item.InvType);
620 string assetContentType = SLUtil.SLAssetTypeToContentType(item.AssetType);
622 if (invContentType != assetContentType)
623 extraData[
"LinkedItemType"] = OSD.FromString(assetContentType);
625 NameValueCollection requestArgs =
new NameValueCollection
627 {
"RequestMethod",
"AddInventoryItem" },
628 {
"ItemID", item.ID.ToString() },
629 {
"AssetID", item.AssetID.ToString() },
630 {
"ParentID", item.Folder.ToString() },
631 {
"OwnerID", item.Owner.ToString() },
632 {
"Name", item.Name },
633 {
"Description", item.Description },
634 {
"CreatorID", item.CreatorId },
635 {
"CreatorData", item.CreatorData },
636 {
"ContentType", invContentType },
637 {
"ExtraData", OSDParser.SerializeJsonString(extraData) }
640 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
641 bool success = response[
"Success"].AsBoolean();
645 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Error creating item " + item.Name +
" for " + item.Owner +
": " +
646 response[
"Message"].AsString());
661 return AddItem(item);
667 return UpdateFolder(folder);
671 public bool MoveItems(UUID ownerID, List<InventoryItemBase> items)
675 while (items.Count > 0)
677 List<InventoryItemBase> currentItems =
new List<InventoryItemBase>();
678 UUID destFolderID = items[0].Folder;
681 for (
int i = 0; i < items.Count; i++)
684 if (item.
Folder == destFolderID)
685 currentItems.Add(item);
689 success &= MoveItems(ownerID, items, destFolderID);
692 for (
int i = 0; i < currentItems.Count; i++)
693 items.Remove(currentItems[i]);
706 return GetRootFolder(userID) != null;
716 OSDArray items = FetchGestures(userID);
718 string[] itemIDs =
new string[items.Count];
719 for (
int i = 0; i < items.Count; i++)
720 itemIDs[i] = items[i].AsUUID().ToString();
730 return new List<InventoryItemBase>(0);
751 return (
int)PermissionMask.All;
754 private List<InventoryFolderBase> GetFoldersFromResponse(
OSDArray items, UUID baseFolder,
bool includeBaseFolder)
756 List<InventoryFolderBase> invFolders =
new List<InventoryFolderBase>(items.Count);
758 for (
int i = 0; i < items.Count; i++)
762 if (item != null && item[
"Type"].AsString() ==
"Folder")
764 UUID folderID = item[
"ID"].AsUUID();
766 if (folderID == baseFolder && !includeBaseFolder)
771 item[
"Name"].AsString(),
772 item[
"OwnerID"].AsUUID(),
773 (
short)SLUtil.ContentTypeToSLAssetType(item[
"ContentType"].AsString()),
774 item[
"ParentID"].AsUUID(),
775 (ushort)item[
"Version"].AsInteger()
784 private List<InventoryItemBase> GetItemsFromResponse(
OSDArray items)
786 List<InventoryItemBase> invItems =
new List<InventoryItemBase>(items.Count);
788 for (
int i = 0; i < items.Count; i++)
790 OSDMap item = items[i] as
OSDMap;
792 if (item != null && item[
"Type"].AsString() ==
"Item")
796 invItem.AssetID = item[
"AssetID"].AsUUID();
797 invItem.AssetType = SLUtil.ContentTypeToSLAssetType(item[
"ContentType"].AsString());
798 invItem.CreationDate = item[
"CreationDate"].AsInteger();
799 invItem.CreatorId = item[
"CreatorID"].AsString();
800 invItem.CreatorData = item[
"CreatorData"].AsString();
801 invItem.Description = item[
"Description"].AsString();
802 invItem.Folder = item[
"ParentID"].AsUUID();
803 invItem.ID = item[
"ID"].AsUUID();
804 invItem.InvType = SLUtil.ContentTypeToSLInvType(item[
"ContentType"].AsString());
805 invItem.Name = item[
"Name"].AsString();
806 invItem.Owner = item[
"OwnerID"].AsUUID();
808 OSDMap extraData = item[
"ExtraData"] as
OSDMap;
809 if (extraData != null && extraData.Count > 0)
811 invItem.Flags = extraData[
"Flags"].AsUInteger();
812 invItem.GroupID = extraData[
"GroupID"].AsUUID();
813 invItem.GroupOwned = extraData[
"GroupOwned"].AsBoolean();
814 invItem.SalePrice = extraData[
"SalePrice"].AsInteger();
815 invItem.SaleType = (byte)extraData[
"SaleType"].AsInteger();
817 OSDMap perms = extraData[
"Permissions"] as
OSDMap;
820 invItem.BasePermissions = perms[
"BaseMask"].AsUInteger();
821 invItem.CurrentPermissions = perms[
"OwnerMask"].AsUInteger();
822 invItem.EveryOnePermissions = perms[
"EveryoneMask"].AsUInteger();
823 invItem.GroupPermissions = perms[
"GroupMask"].AsUInteger();
824 invItem.NextPermissions = perms[
"NextOwnerMask"].AsUInteger();
827 if (extraData.ContainsKey(
"LinkedItemType"))
828 invItem.AssetType = SLUtil.ContentTypeToSLAssetType(extraData[
"LinkedItemType"].AsString());
831 if (invItem.BasePermissions == 0)
833 m_log.InfoFormat(
"[SIMIAN INVENTORY CONNECTOR]: Forcing item permissions to full for item {0} ({1})",
834 invItem.Name, invItem.ID);
836 invItem.CurrentPermissions = (uint)PermissionMask.All;
838 invItem.GroupPermissions = (uint)PermissionMask.All;
842 invItems.Add(invItem);
850 private bool MoveItems(UUID ownerID, List<InventoryItemBase> items, UUID destFolderID)
852 string[] itemIDs =
new string[items.Count];
853 for (
int i = 0; i < items.Count; i++)
854 itemIDs[i] = items[i].ID.ToString();
856 NameValueCollection requestArgs =
new NameValueCollection
858 {
"RequestMethod",
"MoveInventoryNodes" },
859 {
"OwnerID", ownerID.ToString() },
860 {
"FolderID", destFolderID.ToString() },
861 {
"Items", String.Join(
",", itemIDs) }
864 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
865 bool success = response[
"Success"].AsBoolean();
869 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Failed to move " + items.Count +
" items to " +
870 destFolderID +
": " + response[
"Message"].AsString());
876 private void UpdateGesture(UUID userID, UUID itemID,
bool enabled)
878 OSDArray gestures = FetchGestures(userID);
881 for (
int i = 0; i < gestures.Count; i++)
883 UUID gesture = gestures[i].AsUUID();
884 if (gesture != itemID)
885 newGestures.Add(OSD.FromUUID(gesture));
889 newGestures.Add(OSD.FromUUID(itemID));
891 SaveGestures(userID, newGestures);
894 private OSDArray FetchGestures(UUID userID)
896 NameValueCollection requestArgs =
new NameValueCollection
898 {
"RequestMethod",
"GetUser" },
899 {
"UserID", userID.ToString() }
902 OSDMap response = SimianGrid.PostToService(m_userServerUrl, requestArgs);
903 if (response[
"Success"].AsBoolean())
905 OSDMap user = response[
"User"] as
OSDMap;
906 if (user != null && response.ContainsKey(
"Gestures"))
908 OSD gestures = OSDParser.DeserializeJson(response[
"Gestures"].AsString());
909 if (gestures != null && gestures is
OSDArray)
910 return (OSDArray)gestures;
912 m_log.Error(
"[SIMIAN INVENTORY CONNECTOR]: Unrecognized active gestures data for " + userID);
917 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Failed to fetch active gestures for " + userID +
": " +
918 response[
"Message"].AsString());
924 private void SaveGestures(UUID userID,
OSDArray gestures)
926 NameValueCollection requestArgs =
new NameValueCollection
928 {
"RequestMethod",
"AddUserData" },
929 {
"UserID", userID.ToString() },
930 {
"Gestures", OSDParser.SerializeJsonString(gestures) }
933 OSDMap response = SimianGrid.PostToService(m_userServerUrl, requestArgs);
934 if (!response[
"Success"].AsBoolean())
936 m_log.Warn(
"[SIMIAN INVENTORY CONNECTOR]: Failed to save active gestures for " + userID +
": " +
937 response[
"Message"].AsString());
InventoryItemBase GetItem(InventoryItemBase item)
Get an item, given by its UUID
bool DeleteFolders(UUID userID, List< UUID > folderIDs)
Delete an item from the user's inventory
bool DeleteItems(UUID userID, List< UUID > itemIDs)
Delete an item from the user's inventory
OpenMetaverse.StructuredData.OSDArray OSDArray
bool UpdateFolder(InventoryFolderBase folder)
Update a folder in the user's inventory
bool AddItem(InventoryItemBase item)
Add a new item to the user's inventory
bool MoveFolder(InventoryFolderBase folder)
Move an inventory folder to a new location
InventoryFolderBase GetFolder(InventoryFolderBase folder)
Get a folder, given by its UUID
bool PurgeFolder(InventoryFolderBase folder)
Purge an inventory folder of all its items and subfolders.
List< InventoryFolderBase > GetInventorySkeleton(UUID userID)
Gets the skeleton of the inventory – folders only
bool MoveItems(UUID ownerID, List< InventoryItemBase > items)
OpenMetaverse.StructuredData.OSDMap OSDMap
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
List< InventoryItemBase > GetFolderItems(UUID userID, UUID folderID)
Gets the items inside a folder
InventoryFolderBase GetFolderForType(UUID userID, FolderType type)
Gets the user folder for the given folder-type
InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
Get multiple items, given by their UUIDs
OpenSim.Framework.PermissionMask PermissionMask
SimianInventoryServiceConnector()
SimianInventoryServiceConnector(string url)
void PostInitialise()
This is called exactly once after all the shared region-modules have been instanciated and IRegionMod...
InventoryCollection GetFolderContent(UUID userID, UUID folderID)
Gets everything (folders and items) inside a folder
List< InventoryItemBase > GetActiveGestures(UUID userID)
Get the active gestures of the agent.
bool AddFolder(InventoryFolderBase folder)
Add a new folder to the user's inventory
InventoryFolderBase GetRootFolder(UUID userID)
Retrieve the root inventory folder for the given user.
virtual UUID Owner
The agent who's inventory this is contained by
bool HasInventoryForUser(UUID userID)
Does the given user have an inventory structure?
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
Inventory Item - contains all the properties associated with an individual inventory piece...
int GetAssetPermissions(UUID userID, UUID assetID)
Get the union of permissions of all inventory items that hold the given assetID.
OpenMetaverse.StructuredData.OSD OSD
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
bool CreateUserInventory(UUID userID)
Create the entire inventory for a given user
UUID ID
A UUID containing the ID for the inventory node itself
void Initialise(IConfigSource source)
This is called to initialize the region module. For shared modules, this is called exactly once...
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
virtual string Name
The name of the node (64 characters or less)
virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
Gets everything (folders and items) inside a folder
SimianInventoryServiceConnector(IConfigSource source)
Used to serialize a whole inventory for transfer over the network.
bool UpdateItem(InventoryItemBase item)
Update an item in the user's inventory