// Constructors
public InventoryFolderImpl(InventoryFolderBase folderbase)
{
Owner = folderbase.Owner;
ID = folderbase.ID;
Name = folderbase.Name;
ParentID = folderbase.ParentID;
Type = folderbase.Type;
Version = folderbase.Version;
}
/// <summary>
/// Load an item from the archive
/// </summary>
/// <param name="data">The raw item data</param>
/// <param name="loadFolder"> </param>
protected InventoryItemBase LoadItem(byte[] data, InventoryFolderBase loadFolder)
{
InventoryItemBase item = UserInventoryItemSerializer.Deserialize(data);
UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_accountService);
if (UUID.Zero != ospResolvedId)
{
item.CreatorIdAsUuid = ospResolvedId;
// Don't preserve the OSPA in the creator id (which actually gets persisted to the
// database). Instead, replace with the UUID that we found.
item.CreatorId = ospResolvedId.ToString();
item.CreatorData = string.Empty;
}
else if (string.IsNullOrEmpty(item.CreatorData))
{
item.CreatorId = m_userInfo.PrincipalID.ToString();
item.CreatorIdAsUuid = new UUID(item.CreatorId);
}
// Don't use the item ID that's in the file, this could be a local user's folder
//item.ID = UUID.Random();
item.Owner = m_userInfo.PrincipalID;
// Record the creator id for the item's asset so that we can use it later, if necessary, when the asset
// is loaded.
// FIXME: This relies on the items coming before the assets in the TAR file. Need to create stronger
// checks for this, and maybe even an external tool for creating OARs which enforces this, rather than
// relying on native tar tools.
m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid;
// Reset folder ID to the one in which we want to load it
item.Folder = loadFolder.ID;
itemsSavedOff.Add(item);
return item;
}
/// <summary>
/// Replicate the inventory paths in the archive to the user's inventory as necessary.
/// </summary>
/// <param name="iarPath">The item archive path to replicate</param>
/// <param name="rootDestFolder">The root folder for the inventory load</param>
/// <param name="resolvedFolders">
/// The folders that we have resolved so far for a given archive path.
/// This method will add more folders if necessary
/// </param>
/// <param name="loadedNodes">
/// Track the inventory nodes created.
/// </param>
/// <returns>The last user inventory folder created or found for the archive path</returns>
public InventoryFolderBase ReplicateArchivePathToUserInventory(
string iarPath,
InventoryFolderBase rootDestFolder,
ref Dictionary<string, InventoryFolderBase> resolvedFolders,
ref HashSet<InventoryNodeBase> loadedNodes)
{
string iarPathExisting = iarPath;
// MainConsole.Instance.DebugFormat(
// "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID);
InventoryFolderBase destFolder
= ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, ref resolvedFolders);
// MainConsole.Instance.DebugFormat(
// "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]",
// iarPath, iarPathExisting);
string iarPathToCreate = iarPath.Substring(iarPathExisting.Length);
CreateFoldersForPath(destFolder, iarPathExisting, iarPathToCreate, ref resolvedFolders, ref loadedNodes);
return destFolder;
}
/// <summary>
/// Find a folder given a PATH_DELIMITER delimited path starting from this folder
/// </summary>
///
/// This method does not handle paths that contain multiple delimitors
///
/// FIXME: We have no way of distinguishing folders with the same path.
///
/// FIXME: Delimitors which occur in names themselves are not currently escapable.
///
/// <param name="inventoryService">
/// Inventory service to query
/// </param>
/// <param name="startFolder">
/// The folder from which the path starts
/// </param>
/// <param name="path">
/// The path to the required folder.
/// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned.
/// </param>
/// <returns>An empty list if the folder is not found, otherwise a list of all folders that match the name</returns>
public static List<InventoryFolderBase> FindFolderByPath(
IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
{
List<InventoryFolderBase> foundFolders = new List<InventoryFolderBase>();
if (path == string.Empty)
{
foundFolders.Add(startFolder);
return foundFolders;
}
path = path.Trim();
if (path == PATH_DELIMITER.ToString())
{
foundFolders.Add(startFolder);
return foundFolders;
}
// If the path isn't just / then trim any starting extraneous slashes
path = path.TrimStart(new char[] { PATH_DELIMITER });
// MainConsole.Instance.DebugFormat("[INVENTORY ARCHIVE UTILS]: Adjusted path in FindFolderByPath() is [{0}]", path);
string[] components = SplitEscapedPath(path);
components[0] = UnescapePath(components[0]);
//string[] components = path.Split(new string[] { PATH_DELIMITER.ToString() }, 2, StringSplitOptions.None);
InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);
foreach (InventoryFolderBase folder in contents.Folders)
{
if (folder.Name == components[0])
{
if (components.Length > 1)
foundFolders.AddRange(FindFolderByPath(inventoryService, folder, components[1]));
else
foundFolders.Add(folder);
}
}
return foundFolders;
}
/// <summary>
/// Delete a scene object from a scene and place in the given avatar's inventory.
/// Returns the UUID of the newly created asset.
/// </summary>
/// <param name="action"></param>
/// <param name="folderID"></param>
/// <param name="objectGroups"></param>
/// <param name="agentId"></param>
/// <param name="itemID"></param>
public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID,
List<ISceneEntity> objectGroups, UUID agentId, out UUID itemID)
{
itemID = UUID.Zero;
if (objectGroups.Count == 0)
return UUID.Zero;
// Get the user info of the item destination
//
IScenePresence SP = m_scene.GetScenePresence(agentId);
UUID userID = UUID.Zero;
if (action == DeRezAction.Take || action == DeRezAction.AcquireToUserInventory ||
action == DeRezAction.SaveToExistingUserInventoryItem)
{
// Take or take copy require a taker
// Saving changes requires a local user
//
if (SP == null || SP.ControllingClient == null)
return UUID.Zero;
userID = agentId;
}
else
{
// All returns / deletes go to the object owner
//
userID = objectGroups[0].OwnerID;
}
if (userID == UUID.Zero) // Can't proceed
{
return UUID.Zero;
}
// If we're returning someone's item, it goes back to the
// owner's Lost And Found folder.
// Delete is treated like return in this case
// Deleting your own items makes them go to trash
//
InventoryFolderBase folder = null;
InventoryItemBase item = null;
if (DeRezAction.SaveToExistingUserInventoryItem == action)
{
item = m_scene.InventoryService.GetItem(userID, objectGroups[0].RootChild.FromUserInventoryItemID);
//item = userInfo.RootFolder.FindItem(
// objectGroup.RootPart.FromUserInventoryItemID);
if (null == item)
{
MainConsole.Instance.DebugFormat(
"[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
objectGroups[0].Name, objectGroups[0].UUID);
return UUID.Zero;
}
}
else
{
// Folder magic
//
if (action == DeRezAction.Delete)
{
// Deleting someone else's item
//
if (SP == null || SP.ControllingClient == null ||
objectGroups[0].OwnerID != agentId)
{
folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown,
AssetType.LostAndFoundFolder);
}
else
{
folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown,
AssetType.TrashFolder);
}
}
else if (action == DeRezAction.Return)
{
// Dump to lost + found unconditionally
//
folder = m_scene.InventoryService.GetFolderForType(userID, InventoryType.Unknown,
AssetType.LostAndFoundFolder);
}
if (folderID == UUID.Zero && folder == null)
{
//.........这里部分代码省略.........
/// <summary>
/// Create the archive name for a particular folder.
/// </summary>
///
/// These names are prepended with an inventory folder's UUID so that more than one folder can have the
/// same name
///
/// <param name="folder"></param>
/// <returns></returns>
public static string CreateArchiveFolderName(InventoryFolderBase folder)
{
return CreateArchiveFolderName (folder.Name, folder.ID);
}
public virtual void FixInventory(IScene scene, string[] cmd)
{
string userName = MainConsole.Instance.Prompt("Name of user");
UserAccount account = m_UserAccountService.GetUserAccount(null, userName);
if (account == null)
{
MainConsole.Instance.Warn("Could not find user");
return;
}
InventoryFolderBase rootFolder = GetRootFolder(account.PrincipalID);
//Fix having a default root folder
if (rootFolder == null)
{
MainConsole.Instance.Warn("Fixing default root folder...");
List<InventoryFolderBase> skel = GetInventorySkeleton(account.PrincipalID);
if (skel.Count == 0)
{
CreateUserInventory(account.PrincipalID, false);
rootFolder = GetRootFolder(account.PrincipalID);
}
else
{
rootFolder = new InventoryFolderBase
{
Name = "My Inventory",
Type = (short) AssetType.RootFolder,
Version = 1,
ID = skel[0].ParentID,
Owner = account.PrincipalID,
ParentID = UUID.Zero
};
}
}
//Check against multiple root folders
List<InventoryFolderBase> rootFolders = GetRootFolders(account.PrincipalID);
List<UUID> badFolders = new List<UUID>();
if (rootFolders.Count != 1)
{
//No duplicate folders!
foreach (
InventoryFolderBase f in rootFolders.Where(f => !badFolders.Contains(f.ID) && f.ID != rootFolder.ID)
)
{
MainConsole.Instance.Warn("Removing duplicate root folder " + f.Name);
badFolders.Add(f.ID);
}
}
//Fix any root folders that shouldn't be root folders
List<InventoryFolderBase> skeleton = GetInventorySkeleton(account.PrincipalID);
List<UUID> foundFolders = new List<UUID>();
foreach (InventoryFolderBase f in skeleton)
{
if (!foundFolders.Contains(f.ID))
foundFolders.Add(f.ID);
if (f.Name == "My Inventory" && f.ParentID != UUID.Zero)
{
//Merge them all together
badFolders.Add(f.ID);
}
}
foreach (InventoryFolderBase f in skeleton)
{
if ((!foundFolders.Contains(f.ParentID) && f.ParentID != UUID.Zero) ||
f.ID == f.ParentID)
{
//The viewer loses the parentID when something goes wrong
//it puts it in the top where My Inventory should be
//We need to put it back in the My Inventory folder, as the sub folders are right for some reason
f.ParentID = rootFolder.ID;
m_Database.StoreFolder(f);
MainConsole.Instance.WarnFormat("Fixing folder {0}", f.Name);
}
else if (badFolders.Contains(f.ParentID))
{
//Put it back in the My Inventory folder
f.ParentID = rootFolder.ID;
m_Database.StoreFolder(f);
MainConsole.Instance.WarnFormat("Fixing folder {0}", f.Name);
}
else if (f.Type == (short) AssetType.CurrentOutfitFolder)
{
List<InventoryItemBase> items = GetFolderItems(account.PrincipalID, f.ID);
//Check the links!
List<UUID> brokenLinks = new List<UUID>();
foreach (InventoryItemBase item in items)
{
InventoryItemBase linkedItem = null;
if ((linkedItem = GetItem(account.PrincipalID, item.AssetID)) == null)
{
//Broken link...
brokenLinks.Add(item.ID);
}
else if (linkedItem.ID == AvatarWearable.DEFAULT_EYES_ITEM ||
linkedItem.ID == AvatarWearable.DEFAULT_SHAPE_ITEM ||
linkedItem.ID == AvatarWearable.DEFAULT_HAIR_ITEM ||
linkedItem.ID == AvatarWearable.DEFAULT_PANTS_ITEM ||
linkedItem.ID == AvatarWearable.DEFAULT_SHIRT_ITEM ||
linkedItem.ID == AvatarWearable.DEFAULT_SKIN_ITEM)
{
//.........这里部分代码省略.........
请发表评论