diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs index 8b44f72421..d5c062b831 100644 --- a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs +++ b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs @@ -162,7 +162,7 @@ namespace OpenSim.Capabilities.Handlers invFetch.owner_id, invFetch.folder_id, invFetch.owner_id, invFetch.fetch_folders, invFetch.fetch_items, invFetch.sort_order, out version); - if (inv.Folders != null) + if (inv != null && inv.Folders != null) { foreach (InventoryFolderBase invFolder in inv.Folders) { @@ -170,7 +170,7 @@ namespace OpenSim.Capabilities.Handlers } } - if (inv.Items != null) + if (inv != null && inv.Items != null) { foreach (InventoryItemBase invItem in inv.Items) { diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index a8ece794cd..9d8561b69e 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -662,11 +662,11 @@ namespace OpenSim.Framework.Servers.HttpServer } catch (IOException e) { - m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw ", e); + m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e); } catch (Exception e) { - m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw " + e.ToString()); + m_log.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e.StackTrace); SendHTML500(response); } finally diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 3470fa911b..9395233262 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1913,7 +1913,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP folderBlock.FolderID = folder.ID; folderBlock.ParentID = folder.ParentID; - folderBlock.Type = -1; + //folderBlock.Type = -1; + folderBlock.Type = (sbyte)folder.Type; folderBlock.Name = Util.StringToBytes256(folder.Name); return folderBlock; diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index ec260b4fec..0f422ae1ce 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -114,7 +114,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: ViaHGLogin"); if (m_RestrictInventoryAccessAbroad) { - RestoreRootFolderContents(client); + IUserManagement uMan = m_Scenes[0].RequestModuleInterface(); + if (uMan.IsLocalGridUser(client.AgentId)) + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local"); + RestoreRootFolderContents(client); + } + else + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is foreign"); + RestoreSuitcaseFolderContents(client); + } } } } @@ -210,7 +220,20 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer logout = success; // flag for later logout from this grid; this is an HG TP if (success && m_RestrictInventoryAccessAbroad) - RemoveRootFolderContents(sp.ControllingClient); + { + IUserManagement uMan = m_aScene.RequestModuleInterface(); + if (uMan != null && uMan.IsLocalGridUser(sp.UUID)) + { + // local grid user + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local"); + RemoveRootFolderContents(sp.ControllingClient); + } + else + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is foreign"); + RemoveSuitcaseFolderContents(sp.ControllingClient); + } + } return success; } @@ -401,25 +424,40 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); if (root != null) { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing root inventory for user {0}", client.AgentId); + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing root inventory for user {0}", client.Name); InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - UUID[] ids = new UUID[content.Folders.Count]; - int i = 0; + List fids = new List(); + List iids = new List(); + List keep = new List(); + foreach (InventoryFolderBase f in content.Folders) - ids[i++] = f.ID; - inv.SendRemoveInventoryFolders(ids); - ids = new UUID[content.Items.Count]; - i = 0; + { + if (f.Name != "My Suitcase") + { + f.Name = f.Name + " (Unavailable)"; + keep.Add(f); + } + } + + // items directly under the root folder foreach (InventoryItemBase it in content.Items) - ids[i++] = it.ID; - inv.SendRemoveInventoryItems(ids); + it.Name = it.Name + " (Unavailable)"; ; + + // Send the new names + inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray()); + } } } } + private void RemoveSuitcaseFolderContents(IClientAPI client) + { + } + private void RestoreRootFolderContents(IClientAPI client) { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root folder"); if (client is IClientCore) { IClientCore core = (IClientCore)client; @@ -428,21 +466,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (core.TryGet(out inv)) { InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - client.SendBulkUpdateInventory(root); - //if (root != null) - //{ - // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory for user {0}", client.AgentId); - // InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - // m_log.DebugFormat("[XXX]: Folder name {0}, id {1}, parent {2}", root.Name, root.ID, root.ParentID); - // foreach (InventoryItemBase i in content.Items) - // m_log.DebugFormat("[XXX]: Name={0}, folderID={1}", i.Name, i.Folder); + InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - // inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); - //} + inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); } } } + private void RestoreSuitcaseFolderContents(IClientAPI client) + { + } + private GridRegion MakeRegion(AgentCircuitData aCircuit) { GridRegion region = new GridRegion(); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index 4be3804c1f..cf6d2f7905 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -297,14 +297,35 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return m_LocalGridInventoryService.CreateUserInventory(userID); } - public List GetInventorySkeleton(UUID userId) + public List GetInventorySkeleton(UUID userID) { - return m_LocalGridInventoryService.GetInventorySkeleton(userId); + string invURL = GetInventoryServiceURL(userID); + + if (invURL == null) // not there, forward to local inventory connector to resolve + return m_LocalGridInventoryService.GetInventorySkeleton(userID); + + IInventoryService connector = GetConnector(invURL); + + return connector.GetInventorySkeleton(userID); } public InventoryCollection GetUserInventory(UUID userID) { - return null; + string invURL = GetInventoryServiceURL(userID); + m_log.DebugFormat("[HG INVENTORY CONNECTOR]: GetUserInventory for {0} {1}", userID, invURL); + + if (invURL == null) // not there, forward to local inventory connector to resolve + return m_LocalGridInventoryService.GetUserInventory(userID); + + InventoryCollection c = m_Cache.GetUserInventory(userID); + if (c != null) + return c; + + IInventoryService connector = GetConnector(invURL); + c = connector.GetUserInventory(userID); + + m_Cache.Cache(userID, c); + return c; } public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) @@ -362,8 +383,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (invURL == null) // not there, forward to local inventory connector to resolve return m_LocalGridInventoryService.GetFolderContent(userID, folderID); - IInventoryService connector = GetConnector(invURL); + InventoryCollection c = m_Cache.GetFolderContent(userID, folderID); + if (c != null) + { + m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderContent found content in cache " + folderID); + return c; + } + IInventoryService connector = GetConnector(invURL); return connector.GetFolderContent(userID, folderID); } @@ -377,8 +404,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (invURL == null) // not there, forward to local inventory connector to resolve return m_LocalGridInventoryService.GetFolderItems(userID, folderID); - IInventoryService connector = GetConnector(invURL); + List items = m_Cache.GetFolderItems(userID, folderID); + if (items != null) + { + m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems found items in cache " + folderID); + return items; + } + IInventoryService connector = GetConnector(invURL); return connector.GetFolderItems(userID, folderID); } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs index 0fe778dfa6..1e434b9394 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/InventoryCache.cs @@ -12,6 +12,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory private static ExpiringCache m_RootFolders = new ExpiringCache(); private static ExpiringCache> m_FolderTypes = new ExpiringCache>(); + private static ExpiringCache m_Inventories = new ExpiringCache(); public void Cache(UUID userID, InventoryFolderBase root) { @@ -55,5 +56,55 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory return null; } + + public void Cache(UUID userID, InventoryCollection inv) + { + lock (m_Inventories) + m_Inventories.AddOrUpdate(userID, inv, 120); + } + + public InventoryCollection GetUserInventory(UUID userID) + { + InventoryCollection inv = null; + if (m_Inventories.TryGetValue(userID, out inv)) + return inv; + return null; + } + + public InventoryCollection GetFolderContent(UUID userID, UUID folderID) + { + InventoryCollection inv = null; + InventoryCollection c; + if (m_Inventories.TryGetValue(userID, out inv)) + { + c = new InventoryCollection(); + c.UserID = userID; + + c.Folders = inv.Folders.FindAll(delegate(InventoryFolderBase f) + { + return f.ParentID == folderID; + }); + c.Items = inv.Items.FindAll(delegate(InventoryItemBase i) + { + return i.Folder == folderID; + }); + return c; + } + return null; + } + + public List GetFolderItems(UUID userID, UUID folderID) + { + InventoryCollection inv = null; + if (m_Inventories.TryGetValue(userID, out inv)) + { + List items = inv.Items.FindAll(delegate(InventoryItemBase i) + { + return i.Folder == folderID; + }); + return items; + } + return null; + } } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs index 77573c369b..990dffb61a 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs @@ -172,7 +172,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public InventoryCollection GetUserInventory(UUID userID) { - return null; + return m_RemoteConnector.GetUserInventory(userID); } public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) @@ -193,16 +193,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory { InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); - if (UserManager != null) + if (invCol != null && UserManager != null) { // Protect ourselves against the caller subsequently modifying the items list List items = new List(invCol.Items); - Util.FireAndForget(delegate - { - foreach (InventoryItemBase item in items) - UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); - }); + if (items != null && items.Count > 0) + Util.FireAndForget(delegate + { + foreach (InventoryItemBase item in items) + UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); + }); } return invCol; diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 5abd74ff96..10b25edac1 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -36,6 +36,7 @@ using OpenMetaverse.Packets; using log4net; using OpenSim.Framework; using OpenSim.Region.Framework; +using OpenSim.Framework.Client; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes.Serialization; @@ -117,31 +118,42 @@ namespace OpenSim.Region.Framework.Scenes /// public bool AddInventoryItem(InventoryItemBase item) { - if (UUID.Zero == item.Folder) + if (item.Folder != UUID.Zero && InventoryService.AddItem(item)) { - InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); + int userlevel = 0; + if (Permissions.IsGod(item.Owner)) + { + userlevel = 1; + } + EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); + + return true; + } + + // OK so either the viewer didn't send a folderID or AddItem failed + UUID originalFolder = item.Folder; + InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); + if (f != null) + { + m_log.DebugFormat( + "[AGENT INVENTORY]: Found folder {0} type {1} for item {2}", + f.Name, (AssetType)f.Type, item.Name); + + item.Folder = f.ID; + } + else + { + f = InventoryService.GetRootFolder(item.Owner); if (f != null) { -// m_log.DebugFormat( -// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}", -// f.Name, (AssetType)f.Type, item.Name); - item.Folder = f.ID; } else { - f = InventoryService.GetRootFolder(item.Owner); - if (f != null) - { - item.Folder = f.ID; - } - else - { - m_log.WarnFormat( - "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified", - item.Owner, item.Name); - return false; - } + m_log.WarnFormat( + "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified", + item.Owner, item.Name); + return false; } } @@ -153,7 +165,13 @@ namespace OpenSim.Region.Framework.Scenes userlevel = 1; } EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, item.AssetID, item.Name, userlevel); - + + if (originalFolder != UUID.Zero) + { + // Tell the viewer that the item didn't go there + ChangePlacement(item, f); + } + return true; } else @@ -165,7 +183,32 @@ namespace OpenSim.Region.Framework.Scenes return false; } } - + + private void ChangePlacement(InventoryItemBase item, InventoryFolderBase f) + { + ScenePresence sp = GetScenePresence(item.Owner); + if (sp != null) + { + if (sp.ControllingClient is IClientCore) + { + IClientCore core = (IClientCore)sp.ControllingClient; + IClientInventory inv; + + if (core.TryGet(out inv)) + { + InventoryFolderBase parent = new InventoryFolderBase(f.ParentID, f.Owner); + parent = InventoryService.GetFolder(parent); + inv.SendRemoveInventoryItems(new UUID[] { item.ID }); + inv.SendBulkUpdateInventory(new InventoryFolderBase[0], new InventoryItemBase[] { item }); + string message = "The item was placed in folder " + f.Name; + if (parent != null) + message += " under " + parent.Name; + sp.ControllingClient.SendAgentAlertMessage(message, false); + } + } + } + } + /// /// Add the given inventory item to a user's inventory. /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 29825a252e..d8cac66637 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2163,12 +2163,6 @@ namespace OpenSim.Region.Framework.Scenes part.RemoveFromPhysics(); } } - -// if (rootPart.PhysActor != null) -// { -// PhysicsScene.RemovePrim(rootPart.PhysActor); -// rootPart.PhysActor = null; -// } if (UnlinkSceneObject(group, false)) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 2b1fba0fb1..2fcce1c520 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -125,12 +125,14 @@ namespace OpenSim.Region.Framework.Scenes private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// - /// Is this sop a root part? + /// Is this a root part? /// - + /// + /// This will return true even if the whole object is attached to an avatar. + /// public bool IsRoot { - get { return ParentGroup.RootPart == this; } + get { return ParentGroup.RootPart == this; } } #region Fields @@ -159,15 +161,7 @@ namespace OpenSim.Region.Framework.Scenes /// If another thread is simultaneously turning physics off on this part then this refernece could become /// null at any time. /// - public PhysicsActor PhysActor - { - get { return m_physActor; } - set - { -// m_log.DebugFormat("[SOP]: PhysActor set to {0} for {1} {2}", value, Name, UUID); - m_physActor = value; - } - } + public PhysicsActor PhysActor { get; set; } //Xantor 20080528 Sound stuff: // Note: This isn't persisted in the database right now, as the fields for that aren't just there yet. @@ -266,7 +260,6 @@ namespace OpenSim.Region.Framework.Scenes private bool m_passTouches; - private PhysicsActor m_physActor; protected Vector3 m_acceleration; protected Vector3 m_angularVelocity; @@ -1112,6 +1105,14 @@ namespace OpenSim.Region.Framework.Scenes } } + /// + /// The parent ID of this part. + /// + /// + /// If this is a root part which is not attached to an avatar then the value will be 0. + /// If this is a root part which is attached to an avatar then the value is the local id of that avatar. + /// If this is a child part then the value is the local ID of the root part. + /// public uint ParentID { get { return _parentID; } @@ -1488,40 +1489,17 @@ namespace OpenSim.Region.Framework.Scenes if (VolumeDetectActive) isPhantom = false; - // Added clarification.. since A rigid body is an object that you can kick around, etc. - bool RigidBody = isPhysical && !isPhantom; - // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition // or flexible if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible)) { - try - { - PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape( - string.Format("{0}/{1}", Name, UUID), - Shape, - AbsolutePosition, - Scale, - RotationOffset, - RigidBody, - m_localId); - } - catch - { - m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); - PhysActor = null; - } + // Added clarification.. since A rigid body is an object that you can kick around, etc. + bool rigidBody = isPhysical && !isPhantom; - // Basic Physics can also return null as well as an exception catch. - PhysicsActor pa = PhysActor; + PhysicsActor pa = AddToPhysics(rigidBody); if (pa != null) - { - pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info - pa.SetMaterial(Material); - DoPhysicsPropertyUpdate(RigidBody, true); pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0); - } } } } @@ -4322,41 +4300,36 @@ namespace OpenSim.Region.Framework.Scenes if (ParentGroup.Scene == null) return; - if (ParentGroup.Scene.CollidablePrims && PhysActor == null) + if (ParentGroup.Scene.CollidablePrims && pa == null) { - // It's not phantom anymore. So make sure the physics engine get's knowledge of it - PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape( - string.Format("{0}/{1}", Name, UUID), - Shape, - AbsolutePosition, - Scale, - RotationOffset, - UsePhysics, - m_localId); + pa = AddToPhysics(UsePhysics); - PhysActor.SetMaterial(Material); - DoPhysicsPropertyUpdate(UsePhysics, true); - - if (!ParentGroup.IsDeleted) + if (pa != null) { - if (LocalId == ParentGroup.RootPart.LocalId) + pa.SetMaterial(Material); + DoPhysicsPropertyUpdate(UsePhysics, true); + + if (!ParentGroup.IsDeleted) { - ParentGroup.CheckSculptAndLoad(); + if (LocalId == ParentGroup.RootPart.LocalId) + { + ParentGroup.CheckSculptAndLoad(); + } + } + + if ( + ((AggregateScriptEvents & scriptEvents.collision) != 0) || + ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || + ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || + ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || + ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || + ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || + (CollisionSound != UUID.Zero) + ) + { + pa.OnCollisionUpdate += PhysicsCollision; + pa.SubscribeEvents(1000); } - } - - if ( - ((AggregateScriptEvents & scriptEvents.collision) != 0) || - ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || - ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || - ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || - ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || - ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || - (CollisionSound != UUID.Zero) - ) - { - PhysActor.OnCollisionUpdate += PhysicsCollision; - PhysActor.SubscribeEvents(1000); } } else // it already has a physical representation @@ -4418,7 +4391,52 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// This removes the part from physics + /// Adds this part to the physics scene. + /// + /// This method also sets the PhysActor property. + /// Add this prim with a rigid body. + /// + /// The physics actor. null if there was a failure. + /// + private PhysicsActor AddToPhysics(bool rigidBody) + { + PhysicsActor pa; + + try + { + pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( + string.Format("{0}/{1}", Name, UUID), + Shape, + AbsolutePosition, + Scale, + RotationOffset, + rigidBody, + m_localId); + } + catch + { + m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); + pa = null; + } + + // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical + // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor + // being set. + PhysActor = pa; + + // Basic Physics can also return null as well as an exception catch. + if (pa != null) + { + pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info + pa.SetMaterial(Material); + DoPhysicsPropertyUpdate(rigidBody, true); + } + + return pa; + } + + /// + /// This removes the part from the physics scene. /// /// /// This isn't the same as turning off physical, since even without being physical the prim has a physics diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 19dab3260f..a21c66ff26 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3514,6 +3514,22 @@ namespace OpenSim.Region.Framework.Scenes }); } + /// + /// Gets the mass. + /// + /// + /// The mass. + /// + public float GetMass() + { + PhysicsActor pa = PhysicsActor; + + if (pa != null) + return pa.Mass; + else + return 0; + } + internal void PushForce(Vector3 impulse) { if (PhysicsActor != null) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 8d25a62cb8..8223d95484 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2022,27 +2022,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected LSL_Vector GetPartLocalPos(SceneObjectPart part) { m_host.AddScriptLPS(1); - if (part.ParentID == 0) + + Vector3 pos; + + if (!part.IsRoot) { - return new LSL_Vector(part.AbsolutePosition.X, - part.AbsolutePosition.Y, - part.AbsolutePosition.Z); + pos = part.OffsetPosition; } else { - if (m_host.IsRoot) + if (part.ParentGroup.IsAttachment) { - return new LSL_Vector(m_host.AttachedPos.X, - m_host.AttachedPos.Y, - m_host.AttachedPos.Z); + pos = part.AttachedPos; } else { - return new LSL_Vector(part.OffsetPosition.X, - part.OffsetPosition.Y, - part.OffsetPosition.Z); + pos = part.AbsolutePosition; } } + +// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); + + return new LSL_Vector(pos.X, pos.Y, pos.Z); } public void llSetRot(LSL_Rotation rot) @@ -2907,7 +2908,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Float llGetMass() { m_host.AddScriptLPS(1); - return m_host.GetMass(); + + if (m_host.ParentGroup.IsAttachment) + { + ScenePresence attachedAvatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar); + + if (attachedAvatar != null) + { + return attachedAvatar.GetMass(); + } + else + { + return 0; + } + } + else + { + if (m_host.IsRoot) + { + return m_host.ParentGroup.GetMass(); + } + else + { + return m_host.GetMass(); + } + } } public void llCollisionFilter(string name, string id, int accept) @@ -7146,6 +7171,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api switch (code) { case (int)ScriptBaseClass.PRIM_POSITION: + case (int)ScriptBaseClass.PRIM_POS_LOCAL: if (remain < 1) return; @@ -10330,6 +10356,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case ScriptBaseClass.OBJECT_CREATOR: ret.Add(new LSL_String(UUID.Zero.ToString())); break; + // For the following 8 see the Object version below + case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT: + ret.Add(new LSL_Integer(0)); + break; + case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT: + ret.Add(new LSL_Integer(0)); + break; + case ScriptBaseClass.OBJECT_SCRIPT_MEMORY: + ret.Add(new LSL_Integer(0)); + break; + case ScriptBaseClass.OBJECT_SCRIPT_TIME: + ret.Add(new LSL_Float(0)); + break; + case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: + ret.Add(new LSL_Integer(0)); + break; + case ScriptBaseClass.OBJECT_SERVER_COST: + ret.Add(new LSL_Float(0)); + break; + case ScriptBaseClass.OBJECT_STREAMING_COST: + ret.Add(new LSL_Float(0)); + break; + case ScriptBaseClass.OBJECT_PHYSICS_COST: + ret.Add(new LSL_Float(0)); + break; + default: + // Invalid or unhandled constant. + ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); + break; } } @@ -10367,6 +10422,49 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case ScriptBaseClass.OBJECT_CREATOR: ret.Add(new LSL_String(obj.CreatorID.ToString())); break; + // The following 8 I have intentionaly coded to return zero. They are part of + // "Land Impact" calculations. These calculations are probably not applicable + // to OpenSim, required figures (cpu/memory usage) are not currently tracked + // I have intentionally left these all at zero rather than return possibly + // missleading numbers + case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT: + // in SL this currently includes crashed scripts + ret.Add(new LSL_Integer(0)); + break; + case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT: + ret.Add(new LSL_Integer(0)); + break; + case ScriptBaseClass.OBJECT_SCRIPT_MEMORY: + // The value returned in SL for mono scripts is 65536 * number of active scripts + ret.Add(new LSL_Integer(0)); + break; + case ScriptBaseClass.OBJECT_SCRIPT_TIME: + // Average cpu time per simulator frame expended on all scripts in the objetc + ret.Add(new LSL_Float(0)); + break; + case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: + // according to the SL wiki A prim or linkset will have prim + // equivalent of the number of prims in a linkset if it does not + // contain a mesh anywhere in the link set or is not a normal prim + // The value returned in SL for normal prims is prim count + ret.Add(new LSL_Integer(0)); + break; + case ScriptBaseClass.OBJECT_SERVER_COST: + // The value returned in SL for normal prims is prim count + ret.Add(new LSL_Float(0)); + break; + case ScriptBaseClass.OBJECT_STREAMING_COST: + // The value returned in SL for normal prims is prim count * 0.06 + ret.Add(new LSL_Float(0)); + break; + case ScriptBaseClass.OBJECT_PHYSICS_COST: + // The value returned in SL for normal prims is prim count + ret.Add(new LSL_Float(0)); + break; + default: + // Invalid or unhandled constant. + ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); + break; } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 5a53e15882..f58f9d6e49 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -479,6 +479,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int DEBUG_CHANNEL = 0x7FFFFFFF; public const int PUBLIC_CHANNEL = 0x00000000; + // Constants for llGetObjectDetails + public const int OBJECT_UNKNOWN_DETAIL = -1; public const int OBJECT_NAME = 1; public const int OBJECT_DESC = 2; public const int OBJECT_POS = 3; @@ -487,6 +489,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int OBJECT_OWNER = 6; public const int OBJECT_GROUP = 7; public const int OBJECT_CREATOR = 8; + public const int OBJECT_RUNNING_SCRIPT_COUNT = 9; + public const int OBJECT_TOTAL_SCRIPT_COUNT = 10; + public const int OBJECT_SCRIPT_MEMORY = 11; + public const int OBJECT_SCRIPT_TIME = 12; + public const int OBJECT_PRIM_EQUIVALENCE = 13; + public const int OBJECT_SERVER_COST = 14; + public const int OBJECT_STREAMING_COST = 15; + public const int OBJECT_PHYSICS_COST = 16; // Can not be public const? public static readonly vector ZERO_VECTOR = new vector(0.0, 0.0, 0.0); diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs index 040c8405b3..cb9b65da77 100644 --- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs +++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs @@ -114,6 +114,8 @@ namespace OpenSim.Server.Handlers.Asset return HandleCreateUserInventory(request); case "GETINVENTORYSKELETON": return HandleGetInventorySkeleton(request); + case "GETUSERINVENTORY": + return HandleGetUserInventory(request); case "GETROOTFOLDER": return HandleGetRootFolder(request); case "GETFOLDERFORTYPE": @@ -153,7 +155,7 @@ namespace OpenSim.Server.Handlers.Asset } catch (Exception e) { - m_log.DebugFormat("[XINVENTORY HANDLER]: Exception {0}", e); + m_log.DebugFormat("[XINVENTORY HANDLER]: Exception {0}", e.StackTrace); } return FailureResult(); @@ -248,6 +250,45 @@ namespace OpenSim.Server.Handlers.Asset return encoding.GetBytes(xmlString); } + byte[] HandleGetUserInventory(Dictionary request) + { + Dictionary result = new Dictionary(); + UUID principal = UUID.Zero; + UUID.TryParse(request["PRINCIPAL"].ToString(), out principal); + + InventoryCollection icoll = m_InventoryService.GetUserInventory(principal); + if (icoll != null) + { + Dictionary folders = new Dictionary(); + int i = 0; + if (icoll.Folders != null) + { + foreach (InventoryFolderBase f in icoll.Folders) + { + folders["folder_" + i.ToString()] = EncodeFolder(f); + i++; + } + result["FOLDERS"] = folders; + } + if (icoll.Items != null) + { + i = 0; + Dictionary items = new Dictionary(); + foreach (InventoryItemBase it in icoll.Items) + { + items["item_" + i.ToString()] = EncodeItem(it); + i++; + } + result["ITEMS"] = items; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + //m_log.DebugFormat("[XXX]: resp string: {0}", xmlString); + UTF8Encoding encoding = new UTF8Encoding(); + return encoding.GetBytes(xmlString); + } + byte[] HandleGetRootFolder(Dictionary request) { Dictionary result = new Dictionary(); @@ -293,22 +334,27 @@ namespace OpenSim.Server.Handlers.Asset if (icoll != null) { Dictionary folders = new Dictionary(); - int i = 0; - foreach (InventoryFolderBase f in icoll.Folders) + int i = 0; + if (icoll.Folders != null) { - folders["folder_" + i.ToString()] = EncodeFolder(f); - i++; + foreach (InventoryFolderBase f in icoll.Folders) + { + folders["folder_" + i.ToString()] = EncodeFolder(f); + i++; + } + result["FOLDERS"] = folders; } - result["FOLDERS"] = folders; - - i = 0; - Dictionary items = new Dictionary(); - foreach (InventoryItemBase it in icoll.Items) + if (icoll.Items != null) { - items["item_" + i.ToString()] = EncodeItem(it); - i++; + i = 0; + Dictionary items = new Dictionary(); + foreach (InventoryItemBase it in icoll.Items) + { + items["item_" + i.ToString()] = EncodeItem(it); + i++; + } + result["ITEMS"] = items; } - result["ITEMS"] = items; } string xmlString = ServerUtils.BuildXmlResponse(result); diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs index 39e983bfd9..9d96703c1a 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs @@ -111,19 +111,21 @@ namespace OpenSim.Services.Connectors if (ret.Count == 0) return null; - List folders = new List(); + Dictionary folders = (Dictionary)ret["FOLDERS"]; + + List fldrs = new List(); try { - foreach (Object o in ret.Values) - folders.Add(BuildFolder((Dictionary)o)); + foreach (Object o in folders.Values) + fldrs.Add(BuildFolder((Dictionary)o)); } catch (Exception e) { m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception unwrapping folder list: {0}", e.Message); } - return folders; + return fldrs; } public InventoryFolderBase GetRootFolder(UUID principalID) @@ -492,12 +494,41 @@ namespace OpenSim.Services.Connectors return int.Parse(ret["RESULT"].ToString()); } - - // These are either obsolete or unused - // public InventoryCollection GetUserInventory(UUID principalID) { - return null; + InventoryCollection inventory = new InventoryCollection(); + inventory.Folders = new List(); + inventory.Items = new List(); + inventory.UserID = principalID; + + try + { + Dictionary ret = MakeRequest("GETUSERINVENTORY", + new Dictionary { + { "PRINCIPAL", principalID.ToString() } + }); + + if (ret == null) + return null; + if (ret.Count == 0) + return null; + + Dictionary folders = + (Dictionary)ret["FOLDERS"]; + Dictionary items = + (Dictionary)ret["ITEMS"]; + + foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i + inventory.Folders.Add(BuildFolder((Dictionary)o)); + foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i + inventory.Items.Add(BuildItem((Dictionary)o)); + } + catch (Exception e) + { + m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetUserInventory: {0}", e.Message); + } + + return inventory; } public void GetUserInventory(UUID principalID, InventoryReceiptCallback callback) diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs index b29d803e90..2e9bd40cd2 100644 --- a/OpenSim/Services/HypergridService/HGInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGInventoryService.cs @@ -105,6 +105,12 @@ namespace OpenSim.Services.HypergridService return new List(); } + public override InventoryCollection GetUserInventory(UUID userID) + { + // NOGO for this inventory service + return null; + } + public override InventoryFolderBase GetRootFolder(UUID principalID) { //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetRootFolder for {0}", principalID); diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs index cb686e26e6..b6ec558b80 100644 --- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs @@ -59,7 +59,7 @@ namespace OpenSim.Services.HypergridService private UserAccountCache m_Cache; - private ExpiringCache> m_SuitcaseTrees = new ExpiringCache>(); + private ExpiringCache> m_SuitcaseTrees = new ExpiringCache>(); public HGSuitcaseInventoryService(IConfigSource config, string configName) : base(config, configName) @@ -104,11 +104,72 @@ namespace OpenSim.Services.HypergridService return false; } - public override List GetInventorySkeleton(UUID principalID) { - // NOGO for this inventory service - return new List(); + XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); + XInventoryFolder root = GetRootXFolder(principalID); + + List tree = GetFolderTree(suitcase.folderID); + if (tree == null || (tree != null && tree.Count == 0)) + return null; + + List folders = new List(); + foreach (XInventoryFolder x in tree) + { + folders.Add(ConvertToOpenSim(x)); + } + + SetAsRootFolder(suitcase, root); + folders.Add(ConvertToOpenSim(suitcase)); + + return folders; + } + + public override InventoryCollection GetUserInventory(UUID userID) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Get Suitcase inventory for user {0}", userID); + InventoryCollection userInventory = new InventoryCollection(); + userInventory.UserID = userID; + userInventory.Folders = new List(); + userInventory.Items = new List(); + + XInventoryFolder suitcase = GetSuitcaseXFolder(userID); + XInventoryFolder root = GetRootXFolder(userID); + + List tree = GetFolderTree(suitcase.folderID); + if (tree == null || (tree != null && tree.Count == 0)) + { + SetAsRootFolder(suitcase, root); + userInventory.Folders.Add(ConvertToOpenSim(suitcase)); + return userInventory; + } + + List items; + foreach (XInventoryFolder f in tree) + { + // Add the items of this subfolder + items = GetFolderItems(userID, f.folderID); + if (items != null && items.Count > 0) + { + userInventory.Items.AddRange(items); + } + + // Add the folder itself + userInventory.Folders.Add(ConvertToOpenSim(f)); + } + + items = GetFolderItems(userID, suitcase.folderID); + if (items != null && items.Count > 0) + { + userInventory.Items.AddRange(items); + } + + SetAsRootFolder(suitcase, root); + userInventory.Folders.Add(ConvertToOpenSim(suitcase)); + + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetUserInventory for user {0} returning {1} folders and {2} items", + userID, userInventory.Folders.Count, userInventory.Items.Count); + return userInventory; } public override InventoryFolderBase GetRootFolder(UUID principalID) @@ -131,51 +192,92 @@ namespace OpenSim.Services.HypergridService { m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder. Creating it...", principalID); // make one, and let's add it to the user's inventory as a direct child of the root folder + // In the DB we tag it as type 100, but we use -1 (Unknown) outside suitcase = CreateFolder(principalID, root.folderID, 100, "My Suitcase"); if (suitcase == null) m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to create suitcase folder"); - m_Database.StoreFolder(suitcase); + + // Create System folders + CreateSystemFolders(principalID, suitcase.folderID); } - // Now let's change the folder ID to match that of the real root folder - SetAsRootFolder(suitcase, root.folderID); + SetAsRootFolder(suitcase, root); return ConvertToOpenSim(suitcase); } + protected void CreateSystemFolders(UUID principalID, UUID rootID) + { + m_log.Debug("[HG SUITCASE INVENTORY SERVICE]: Creating System folders under Suitcase..."); + XInventoryFolder[] sysFolders = GetSystemFolders(principalID, rootID); + + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Animation) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Animation, "Animations"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Bodypart) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Bodypart, "Body Parts"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.CallingCard) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.CallingCard, "Calling Cards"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Clothing) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Clothing, "Clothing"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Gesture) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Gesture, "Gestures"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Landmark) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Landmark, "Landmarks"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.LostAndFoundFolder) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.LostAndFoundFolder, "Lost And Found"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Notecard) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Notecard, "Notecards"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Object) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Object, "Objects"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.SnapshotFolder) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.SnapshotFolder, "Photo Album"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.LSLText) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.LSLText, "Scripts"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Sound) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Sound, "Sounds"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.Texture) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.Texture, "Textures"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.TrashFolder) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.TrashFolder, "Trash"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.FavoriteFolder) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.FavoriteFolder, "Favorites"); + if (!Array.Exists(sysFolders, delegate(XInventoryFolder f) { if (f.type == (int)AssetType.CurrentOutfitFolder) return true; return false; })) + CreateFolder(principalID, rootID, (int)AssetType.CurrentOutfitFolder, "Current Outfit"); + + } + public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) { //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type); - return GetRootFolder(principalID); + XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "type", "parentFolderID" }, + new string[] { principalID.ToString(), ((int)type).ToString(), suitcase.folderID.ToString() }); + + if (folders.Length == 0) + { + m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Found no folder for type {0} for user {1}", type, principalID); + return null; + } + + m_log.DebugFormat( + "[HG SUITCASE INVENTORY SERVICE]: Found folder {0} {1} for type {2} for user {3}", + folders[0].folderName, folders[0].folderID, type, principalID); + + return ConvertToOpenSim(folders[0]); } public override InventoryCollection GetFolderContent(UUID principalID, UUID folderID) { InventoryCollection coll = null; XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); - XInventoryFolder root = GetRootXFolder(principalID); - if (!IsWithinSuitcaseTree(folderID, root, suitcase)) + if (!IsWithinSuitcaseTree(folderID, suitcase)) return new InventoryCollection(); - if (folderID == root.folderID) // someone's asking for the root folder, we'll give them the suitcase - { - if (suitcase != null) - { - coll = base.GetFolderContent(principalID, suitcase.folderID); - foreach (InventoryFolderBase f in coll.Folders) - f.ParentID = root.folderID; - foreach (InventoryItemBase i in coll.Items) - i.Folder = root.folderID; - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderContent for root folder returned content for suitcase folder"); - } - } - else - { - coll = base.GetFolderContent(principalID, folderID); - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderContent for non-root folder {0}", folderID); - } + coll = base.GetFolderContent(principalID, folderID); + if (coll == null) { m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Something wrong with user {0}'s suitcase folder", principalID); @@ -188,10 +290,9 @@ namespace OpenSim.Services.HypergridService { // Let's do a bit of sanity checking, more than the base service does // make sure the given folder exists under the suitcase tree of this user - XInventoryFolder root = GetRootXFolder(principalID); XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); - if (!IsWithinSuitcaseTree(folderID, root, suitcase)) + if (!IsWithinSuitcaseTree(folderID, suitcase)) return new List(); return base.GetFolderItems(principalID, folderID); @@ -199,52 +300,40 @@ namespace OpenSim.Services.HypergridService public override bool AddFolder(InventoryFolderBase folder) { + m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID); // Let's do a bit of sanity checking, more than the base service does // make sure the given folder's parent folder exists under the suitcase tree of this user - XInventoryFolder root = GetRootXFolder(folder.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); - if (!IsWithinSuitcaseTree(folder.ParentID, root, suitcase)) + if (!IsWithinSuitcaseTree(folder.ParentID, suitcase)) return false; // OK, it's legit - // Check if it's under the Root folder directly - if (folder.ParentID == root.folderID) - { - // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder for root folder for user {0}. Adding in suitcase instead", folder.Owner); - folder.ParentID = suitcase.folderID; - } - return base.AddFolder(folder); - } + } - public bool UpdateFolder(InventoryFolderBase folder) + public override bool UpdateFolder(InventoryFolderBase folder) { - XInventoryFolder root = GetRootXFolder(folder.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); - if (!IsWithinSuitcaseTree(folder.ID, root, suitcase)) + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version); + if (!IsWithinSuitcaseTree(folder.ID, suitcase)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name); return false; + } + // For all others return base.UpdateFolder(folder); } public override bool MoveFolder(InventoryFolderBase folder) { - XInventoryFolder root = GetRootXFolder(folder.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); - if (!IsWithinSuitcaseTree(folder.ID, root, suitcase) || !IsWithinSuitcaseTree(folder.ParentID, root, suitcase)) + if (!IsWithinSuitcaseTree(folder.ID, suitcase) || !IsWithinSuitcaseTree(folder.ParentID, suitcase)) return false; - if (folder.ParentID == root.folderID) - { - // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveFolder to root folder for user {0}. Moving it to suitcase instead", folder.Owner); - folder.ParentID = suitcase.folderID; - } - return base.MoveFolder(folder); } @@ -264,31 +353,21 @@ namespace OpenSim.Services.HypergridService { // Let's do a bit of sanity checking, more than the base service does // make sure the given folder's parent folder exists under the suitcase tree of this user - XInventoryFolder root = GetRootXFolder(item.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); - if (!IsWithinSuitcaseTree(item.Folder, root, suitcase)) + if (!IsWithinSuitcaseTree(item.Folder, suitcase)) return false; // OK, it's legit - // Check if it's under the Root folder directly - if (item.Folder == root.folderID) - { - // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddItem for root folder for user {0}. Adding in suitcase instead", item.Owner); - item.Folder = suitcase.folderID; - } - return base.AddItem(item); } public override bool UpdateItem(InventoryItemBase item) { - XInventoryFolder root = GetRootXFolder(item.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); - if (!IsWithinSuitcaseTree(item.Folder, root, suitcase)) + if (!IsWithinSuitcaseTree(item.Folder, suitcase)) return false; return base.UpdateItem(item); @@ -298,68 +377,64 @@ namespace OpenSim.Services.HypergridService { // Principal is b0rked. *sigh* - XInventoryFolder root = GetRootXFolder(items[0].Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(items[0].Owner); - if (!IsWithinSuitcaseTree(items[0].Folder, root, suitcase)) + if (!IsWithinSuitcaseTree(items[0].Folder, suitcase)) return false; - foreach (InventoryItemBase it in items) - if (it.Folder == root.folderID) - { - // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveItem to root folder for user {0}. Moving it to suitcase instead", it.Owner); - it.Folder = suitcase.folderID; - } - return base.MoveItems(principalID, items); } - // Let these pass. Use inherited methods. public override bool DeleteItems(UUID principalID, List itemIDs) { return false; } - public override InventoryItemBase GetItem(InventoryItemBase item) + public new InventoryItemBase GetItem(InventoryItemBase item) { InventoryItemBase it = base.GetItem(item); - XInventoryFolder root = GetRootXFolder(it.Owner); - XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner); - - if (it != null) + if (it == null) { - if (!IsWithinSuitcaseTree(it.Folder, root, suitcase)) - return null; - - if (it.Folder == suitcase.folderID) - it.Folder = root.folderID; - - // UserAccount user = m_Cache.GetUser(it.CreatorId); - - // // Adjust the creator data - // if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty)) - // it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName; - //} + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve item {0} ({1}) in folder {2}", + item.Name, item.ID, item.Folder); + return null; } + XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner); + if (suitcase == null) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Root or Suitcase are null for user {0}", + it.Owner); + return null; + } + + if (!IsWithinSuitcaseTree(it.Folder, suitcase)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase", + it.Name, it.Folder); + return null; + } + + // UserAccount user = m_Cache.GetUser(it.CreatorId); + + // // Adjust the creator data + // if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty)) + // it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName; + //} return it; } - public override InventoryFolderBase GetFolder(InventoryFolderBase folder) + public new InventoryFolderBase GetFolder(InventoryFolderBase folder) { InventoryFolderBase f = base.GetFolder(folder); - XInventoryFolder root = GetRootXFolder(f.Owner); - XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner); if (f != null) { - if (!IsWithinSuitcaseTree(f.ID, root, suitcase)) - return null; + XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner); - if (f.ParentID == suitcase.folderID) - f.ParentID = root.folderID; + if (!IsWithinSuitcaseTree(f.ID, suitcase)) + return null; } return f; @@ -409,20 +484,19 @@ namespace OpenSim.Services.HypergridService return null; } - private void SetAsRootFolder(XInventoryFolder suitcase, UUID rootID) + private void SetAsRootFolder(XInventoryFolder suitcase, XInventoryFolder root) { - suitcase.folderID = rootID; - suitcase.parentFolderID = UUID.Zero; + suitcase.type = (short)AssetType.Folder; } - private List GetFolderTree(UUID root) + private List GetFolderTree(UUID folder) { List t = null; - if (m_SuitcaseTrees.TryGetValue(root, out t)) + if (m_SuitcaseTrees.TryGetValue(folder, out t)) return t; - t = GetFolderTreeRecursive(root); - m_SuitcaseTrees.AddOrUpdate(root, t, 120); + t = GetFolderTreeRecursive(folder); + m_SuitcaseTrees.AddOrUpdate(folder, t, 120); return t; } @@ -447,10 +521,17 @@ namespace OpenSim.Services.HypergridService } - private bool IsWithinSuitcaseTree(UUID folderID, XInventoryFolder root, XInventoryFolder suitcase) + /// + /// Return true if the folderID is a subfolder of the Suitcase or the suitcase folder itself + /// + /// + /// + /// + /// + private bool IsWithinSuitcaseTree(UUID folderID, XInventoryFolder suitcase) { List tree = new List(); - tree.Add(root); // Warp! the tree is the real root folder plus the children of the suitcase folder + tree.Add(suitcase); // Warp! the tree is the real root folder plus the children of the suitcase folder tree.AddRange(GetFolderTree(suitcase.folderID)); XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl) { @@ -463,4 +544,5 @@ namespace OpenSim.Services.HypergridService } #endregion } + } diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 7b2c3a6aff..0e7a3584e2 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -40,9 +40,9 @@ namespace OpenSim.Services.InventoryService { public class XInventoryService : ServiceBase, IInventoryService { -// private static readonly ILog m_log = -// LogManager.GetLogger( -// MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); protected IXInventoryData m_Database; protected bool m_AllowDelete = true; @@ -113,7 +113,7 @@ namespace OpenSim.Services.InventoryService result = true; } - XInventoryFolder[] sysFolders = GetSystemFolders(principalID); + XInventoryFolder[] sysFolders = GetSystemFolders(principalID, rootFolder.ID); if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Animation) return true; return false; })) CreateFolder(principalID, rootFolder.ID, (int)AssetType.Animation, "Animations"); @@ -163,13 +163,13 @@ namespace OpenSim.Services.InventoryService return newFolder; } - protected virtual XInventoryFolder[] GetSystemFolders(UUID principalID) + protected virtual XInventoryFolder[] GetSystemFolders(UUID principalID, UUID rootID) { // m_log.DebugFormat("[XINVENTORY SERVICE]: Getting system folders for {0}", principalID); XInventoryFolder[] allFolders = m_Database.GetFolders( - new string[] { "agentID" }, - new string[] { principalID.ToString() }); + new string[] { "agentID", "parentFolderID" }, + new string[] { principalID.ToString(), rootID.ToString() }); XInventoryFolder[] sysFolders = Array.FindAll( allFolders, @@ -301,16 +301,26 @@ namespace OpenSim.Services.InventoryService public virtual bool AddFolder(InventoryFolderBase folder) { + //m_log.DebugFormat("[XINVENTORY]: Add folder {0} type {1} in parent {2}", folder.Name, folder.Type, folder.ParentID); InventoryFolderBase check = GetFolder(folder); if (check != null) return false; - XInventoryFolder xFolder = ConvertFromOpenSim(folder); - return m_Database.StoreFolder(xFolder); + if (folder.Type == (short)AssetType.Folder || folder.Type == (short)AssetType.Unknown || + GetFolderForType(folder.Owner, (AssetType)(folder.Type)) == null) + { + XInventoryFolder xFolder = ConvertFromOpenSim(folder); + return m_Database.StoreFolder(xFolder); + } + else + m_log.DebugFormat("[XINVENTORY]: Folder {0} of type {1} already exists", folder.Name, folder.Type); + + return false; } public virtual bool UpdateFolder(InventoryFolderBase folder) { + //m_log.DebugFormat("[XINVENTORY]: Update folder {0} {1} ({2})", folder.Name, folder.Type, folder.ID); XInventoryFolder xFolder = ConvertFromOpenSim(folder); InventoryFolderBase check = GetFolder(folder); if (check == null) @@ -319,9 +329,13 @@ namespace OpenSim.Services.InventoryService if (check.Type != -1 || xFolder.type != -1) { if (xFolder.version < check.Version) + { + //m_log.DebugFormat("[XINVENTORY]: {0} < {1} can't do", xFolder.version, check.Version); return false; + } check.Version = (ushort)xFolder.version; xFolder = ConvertFromOpenSim(check); + //m_log.DebugFormat("[XINVENTORY]: Storing {0} {1} {2}", xFolder.folderName, xFolder.version, xFolder.type); return m_Database.StoreFolder(xFolder); } @@ -499,13 +513,30 @@ namespace OpenSim.Services.InventoryService return m_Database.GetAssetPermissions(principalID, assetID); } - // CM never needed those. Left unimplemented. - // Obsolete in core - // - public InventoryCollection GetUserInventory(UUID userID) + public virtual InventoryCollection GetUserInventory(UUID userID) { - return null; + InventoryCollection userInventory = new InventoryCollection(); + userInventory.UserID = userID; + userInventory.Folders = new List(); + userInventory.Items = new List(); + + List skel = GetInventorySkeleton(userID); + if (skel != null) + { + foreach (InventoryFolderBase f in skel) + { + InventoryCollection c = GetFolderContent(userID, f.ID); + if (c != null && c.Items != null && c.Items.Count > 0) + userInventory.Items.AddRange(c.Items); + if (c != null && c.Folders != null && c.Folders.Count > 0) + userInventory.Folders.AddRange(c.Folders); + } + } + m_log.DebugFormat("[XINVENTORY SERVICE]: GetUserInventory for user {0} returning {1} folders and {2} items", + userID, userInventory.Folders.Count, userInventory.Items.Count); + return userInventory; } + public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) { } @@ -525,6 +556,9 @@ namespace OpenSim.Services.InventoryService newFolder.ParentID = folder.parentFolderID; newFolder.Type = (short)folder.type; + // Viewer can't understand anything that's not in it's LLFolderType enum + if (newFolder.Type == 100) + newFolder.Type = -1; newFolder.Version = (ushort)folder.version; newFolder.Name = folder.folderName; newFolder.Owner = folder.agentID;