From 633f4bb3d80decf4773ee577bacb153fbb4be738 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 3 Apr 2012 09:28:17 +0100 Subject: [PATCH 01/23] remove possible PhysActor unexpectedly null race conditions when changing prim collision status factor out common SOP physics scene adding code into a common SOP.AddToPhysics() that is the counterpart to the existing RemoveFromPhysics() --- OpenSim/Region/Framework/Scenes/Scene.cs | 6 - .../Framework/Scenes/SceneObjectPart.cs | 131 ++++++++++-------- 2 files changed, 74 insertions(+), 63 deletions(-) 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..9e65f5d5fe 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1488,40 +1488,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 +4299,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 +4390,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 From 600a86bcaeb78089165f7d778661edbfdface047 Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 10:02:18 +0200 Subject: [PATCH 02/23] Little bug fix in HasGroupAccess, to properly store the case "true" in the cache. --- OpenSim/Region/CoreModules/World/Land/LandObject.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index c532d0d645..ced7b523b2 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -446,7 +446,7 @@ namespace OpenSim.Region.CoreModules.World.Land { if (d.GroupID == LandData.GroupID) { - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); return true; } } @@ -454,10 +454,7 @@ namespace OpenSim.Region.CoreModules.World.Land return false; } - if (!sp.ControllingClient.IsGroupMember(LandData.GroupID)) - return false; - - return true; + return sp.ControllingClient.IsGroupMember(LandData.GroupID); } return false; } From e4406c846d74212493890a46922292cd7fec2ea5 Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 10:25:54 +0200 Subject: [PATCH 03/23] Group based access restrictions to parcels require group membership, but not that this group is active for that user. --- .../CoreModules/World/Land/LandObject.cs | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index ced7b523b2..a7c7cc5234 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -424,37 +424,34 @@ namespace OpenSim.Region.CoreModules.World.Land { if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) { - ScenePresence sp; - if (!m_scene.TryGetScenePresence(avatar, out sp)) + bool isMember; + if (m_groupMemberCache.TryGetValue(avatar, out isMember)) + return isMember; + + IGroupsModule groupsModule = m_scene.RequestModuleInterface(); + if (groupsModule == null) { - bool isMember; - if (m_groupMemberCache.TryGetValue(avatar, out isMember)) - return isMember; - - IGroupsModule groupsModule = m_scene.RequestModuleInterface(); - if (groupsModule == null) - return false; - - GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); - if (membership == null || membership.Length == 0) - { - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); - return false; - } - - foreach (GroupMembershipData d in membership) - { - if (d.GroupID == LandData.GroupID) - { - m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); - return true; - } - } m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); return false; } - return sp.ControllingClient.IsGroupMember(LandData.GroupID); + GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); + if (membership == null || membership.Length == 0) + { + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; + } + + foreach (GroupMembershipData d in membership) + { + if (d.GroupID == LandData.GroupID) + { + m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); + return true; + } + } + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; } return false; } From 8f45eb913c6fad38735f00db818e03c4123904aa Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 11:10:05 +0200 Subject: [PATCH 04/23] Revert last commit --- .../CoreModules/World/Land/LandObject.cs | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index a7c7cc5234..ced7b523b2 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -424,34 +424,37 @@ namespace OpenSim.Region.CoreModules.World.Land { if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) { - bool isMember; - if (m_groupMemberCache.TryGetValue(avatar, out isMember)) - return isMember; - - IGroupsModule groupsModule = m_scene.RequestModuleInterface(); - if (groupsModule == null) + ScenePresence sp; + if (!m_scene.TryGetScenePresence(avatar, out sp)) { - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); - return false; - } + bool isMember; + if (m_groupMemberCache.TryGetValue(avatar, out isMember)) + return isMember; - GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); - if (membership == null || membership.Length == 0) - { - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); - return false; - } + IGroupsModule groupsModule = m_scene.RequestModuleInterface(); + if (groupsModule == null) + return false; - foreach (GroupMembershipData d in membership) - { - if (d.GroupID == LandData.GroupID) + GroupMembershipData[] membership = groupsModule.GetMembershipData(avatar); + if (membership == null || membership.Length == 0) { - m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); - return true; + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; } + + foreach (GroupMembershipData d in membership) + { + if (d.GroupID == LandData.GroupID) + { + m_groupMemberCache.Add(avatar, true, m_groupMemberCacheTimeout); + return true; + } + } + m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); + return false; } - m_groupMemberCache.Add(avatar, false, m_groupMemberCacheTimeout); - return false; + + return sp.ControllingClient.IsGroupMember(LandData.GroupID); } return false; } From 67537f359688bfa592312baf808e9d399fc164fa Mon Sep 17 00:00:00 2001 From: Snoopy Pfeffer Date: Thu, 5 Apr 2012 13:03:57 +0200 Subject: [PATCH 05/23] Added missing refresh of group membership client side cache to the groups module. Before memberships of non active groups often were not stored in the cache (n_groupPowers). --- .../Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 2a15e5d6f6..e669f4c74c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1294,7 +1294,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups OnAgentDataUpdateRequest(remoteClient, dataForAgentID, UUID.Zero); - // Need to send a group membership update to the client // UDP version doesn't seem to behave nicely. But we're going to send it out here // with an empty group membership to hopefully remove groups being displayed due @@ -1305,6 +1304,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray); remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray); + if (remoteClient.AgentId == dataForAgentID) + remoteClient.RefreshGroupMembership(); } /// From cdbe34716f78072168189e30ac5d6b8e7bcc91ef Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:21:27 -0700 Subject: [PATCH 06/23] Thank you, BaseHttpServer, for telling me where things go wrong. --- OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 From e324fb241505c92ea845421280c4a8ca372e3ded Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:22:30 -0700 Subject: [PATCH 07/23] Guard against null inventory contents. --- .../WebFetchInventoryDescendents/WebFetchInvDescHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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) { From 8fd86c91561ade716a9179653e9ffb75ff1df438 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:24:34 -0700 Subject: [PATCH 08/23] Packing of folder in SendBulkUpdateInventory always set the folder type to -1. Not sure if there's a reason for it, but I'm changing it to the given folder type. --- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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; From 6eaff18961668ba6141a7dd26a3df873489f64b5 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:38:47 -0700 Subject: [PATCH 09/23] Finish the implementation of GetUserInventory, even though it's still not used. --- .../Inventory/HGInventoryBroker.cs | 43 +++++++++-- .../Inventory/InventoryCache.cs | 51 +++++++++++++ .../RemoteXInventoryServiceConnector.cs | 15 ++-- .../Inventory/XInventoryInConnector.cs | 72 +++++++++++++++---- .../Inventory/XInventoryConnector.cs | 47 +++++++++--- .../HypergridService/HGInventoryService.cs | 6 ++ 6 files changed, 201 insertions(+), 33 deletions(-) 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/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); From 953fe46811d4c35378526bc58d950c72da64aa70 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:48:41 -0700 Subject: [PATCH 10/23] A few minor tweaks here and there in XInventoryService. --- .../InventoryService/XInventoryService.cs | 62 ++++++++++++++----- 1 file changed, 48 insertions(+), 14 deletions(-) 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; From 25b3edc21c4d5deb7563410a4e0a5364153b1002 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:51:12 -0700 Subject: [PATCH 11/23] WARNING: LOTS OF COMMENTED AND UNUSED CODE IN THIS COMMIT. This is on purpose; it's an historical record of what works and what doesn't wrt manipulating inventory at the viewer. I'll remove the unused code in a subsequent commit, but wanted to place it in history. The uncommented code works. --- .../EntityTransfer/HGEntityTransferModule.cs | 318 +++++++- .../HGSuitcaseInventoryService.cs | 752 +++++++++++++++++- 2 files changed, 1010 insertions(+), 60 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index ec260b4fec..d85a996c5f 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; } @@ -388,6 +411,36 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #endregion + // COMPLETE FAIL + //private void RemoveRootFolderContents(IClientAPI client) + //{ + // InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing root inventory for user {0}, version {1}", client.AgentId, root.Version); + // InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); + + // List keep = new List(); + // foreach (InventoryFolderBase f in content.Folders) + // { + // if (f.Type == (short)AssetType.TrashFolder || f.Type == (short)AssetType.Landmark || + // f.Type == (short)AssetType.FavoriteFolder || f.Type == (short)AssetType.CurrentOutfitFolder) + // { + // // Don't remove these because the viewer refuses to exist without them + // // and immediately sends a request to create them again, which makes things + // // very confusing in the viewer. + // // Just change their names + // f.Name = "Home " + f.Name + " (Unavailable)"; + // keep.Add(f); + // } + // else + // { + // m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); + // } + // } + + + // client.SendInventoryFolderDetails(client.AgentId, root.ID, new List(), keep, root.Version + 1, true, true); + //} + private void RemoveRootFolderContents(IClientAPI client) { // TODO tell the viewer to remove the root folder's content @@ -401,25 +454,60 @@ 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)"; ; + + // next, add the subfolders and items of the keep folders + //foreach (InventoryFolderBase f in keep) + //{ + // InventoryCollection c = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, f.ID); + // foreach (InventoryFolderBase sf in c.Folders) + // { + // m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); + // fids.Add(sf.ID); + // } + // foreach (InventoryItemBase it in c.Items) + // iids.Add(it.ID); + //} + + //inv.SendRemoveInventoryFolders(fids.ToArray()); + + // Increase the version number + //root.Version += 1; + //m_Scenes[0].InventoryService.UpdateFolder(root); + //foreach (InventoryFolderBase f in keep) + //{ + // f.Version += 1; + // m_Scenes[0].InventoryService.UpdateFolder(f); + //} + + // Send the new names and versions + inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray()); + } } } } - private void RestoreRootFolderContents(IClientAPI client) + private void RemoveRootFolderContents2(IClientAPI client) { + // TODO tell the viewer to remove the root folder's content if (client is IClientCore) { IClientCore core = (IClientCore)client; @@ -428,21 +516,207 @@ 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); + if (root != null) + { + 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); + List fids = new List(); + List iids = new List(); + List keep = new List(); - // inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); - //} + foreach (InventoryFolderBase f in content.Folders) + { + if (f.Type == (short)AssetType.TrashFolder || f.Type == (short)AssetType.Landmark || + f.Type == (short)AssetType.FavoriteFolder || f.Type == (short)AssetType.CurrentOutfitFolder) + { + // Don't remove these because the viewer refuses to exist without them + // and immediately sends a request to create them again, which makes things + // very confusing in the viewer. + // Just change their names + f.Name = "Home " + f.Name + " (Unavailable)"; + keep.Add(f); + } + else + { + m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); + fids.Add(f.ID); + } + } + + foreach (InventoryItemBase it in content.Items) + iids.Add(it.ID); + + // next, add the subfolders and items of the keep folders + foreach (InventoryFolderBase f in keep) + { + InventoryCollection c = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, f.ID); + foreach (InventoryFolderBase sf in c.Folders) + { + m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); + fids.Add(sf.ID); + } + foreach (InventoryItemBase it in c.Items) + iids.Add(it.ID); + } + + inv.SendRemoveInventoryFolders(fids.ToArray()); + inv.SendRemoveInventoryItems(iids.ToArray()); + + // Increase the version number + root.Version += 1; + m_Scenes[0].InventoryService.UpdateFolder(root); + //foreach (InventoryFolderBase f in keep) + //{ + // f.Version += 1; + // m_Scenes[0].InventoryService.UpdateFolder(f); + //} + + // Send the new names and versions + inv.SendBulkUpdateInventory(keep.ToArray(), new InventoryItemBase[0]); + + } } } } + private void RemoveSuitcaseFolderContents(IClientAPI client) + { + return; + + //// TODO tell the viewer to remove the suitcase folder's content + //if (client is IClientCore) + //{ + // IClientCore core = (IClientCore)client; + // IClientInventory inv; + + // if (core.TryGet(out inv)) + // { + // InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + // if (root != null) + // { + // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing suitcase inventory for user {0}", client.Name); + // InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); + // List fids = new List(); + // List iids = new List(); + + // if (content.Folders.Count == 0) + // m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: no subfolders???"); + // foreach (InventoryFolderBase f in content.Folders) + // { + // m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); + // fids.Add(f.ID); + // } + + // foreach (InventoryItemBase it in content.Items) + // iids.Add(it.ID); + + // inv.SendRemoveInventoryFolders(fids.ToArray()); + // inv.SendRemoveInventoryItems(iids.ToArray()); + + // // Increase the version number + // root.Version += 1; + // m_Scenes[0].InventoryService.UpdateFolder(root); + // } + // } + //} + } + + private void RestoreRootFolderContents(IClientAPI client) + { + // This works! + //InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + //client.SendBulkUpdateInventory(root); + + // SORTA KINDA some items are missing... + //InventoryCollection userInventory = m_Scenes[0].InventoryService.GetUserInventory(client.AgentId); + //InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + //client.SendBulkUpdateInventory(root); + + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root folder"); + if (client is IClientCore) + { + IClientCore core = (IClientCore)client; + IClientInventory inv; + + if (core.TryGet(out inv)) + { + InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); + + inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); + } + } + + // ATTEMPT # 3 -- STILL DOESN'T WORK! + //if (client is IClientCore) + //{ + // IClientCore core = (IClientCore)client; + // IClientInventory inv; + + // if (core.TryGet(out inv)) + // { + // InventoryCollection userInventory = m_Scenes[0].InventoryService.GetUserInventory(client.AgentId); + // if (userInventory != null) + // { + // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory for user {0}", client.AgentId); + // foreach (InventoryFolderBase f in userInventory.Folders) + // m_log.DebugFormat("[AAA]: FOLDER {0} {1} {2} {3} {4}", f.Name, f.Type, f.Version, f.ID, f.ParentID); + // foreach (InventoryItemBase f in userInventory.Items) + // m_log.DebugFormat("[AAA]: ITEM {0} {1} {2}", f.Name, f.ID, f.Folder); + // inv.SendBulkUpdateInventory(userInventory.Folders.ToArray(), userInventory.Items.ToArray()); + // } + // else + // m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve inventory for user {0}", client.AgentId); + // } + //} + + + // ATTEMPT #2 -- BETTER THAN 1, BUT STILL DOES NOT WORK WELL + //if (client is IClientCore) + //{ + // IClientCore core = (IClientCore)client; + // IClientInventory inv; + + // if (core.TryGet(out inv)) + // { + // List skel = m_Scenes[0].InventoryService.GetInventorySkeleton(client.AgentId); + // if (skel != null) + // { + // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory for user {0}", client.AgentId); + // foreach (InventoryFolderBase f in skel) + // m_log.DebugFormat("[AAA]: {0} {1} {2} {3} {4}", f.Name, f.Type, f.Version, f.ID, f.ParentID); + // inv.SendBulkUpdateInventory(skel.ToArray(), new InventoryItemBase[0]); + // } + // else + // m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve skeleton for user {0}", client.AgentId); + + // ATTEMPT #1 -- DOES NOT WORK + //InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + //if (root != null) + //{ + //InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); + //InventoryFolderBase[] folders = new InventoryFolderBase[content.Folders.Count + 1]; + //m_log.DebugFormat("[AAA]: Folder name {0}, id {1}, version {2}, parent {3}", root.Name, root.ID, root.Version, root.ParentID); + //folders[0] = root; + //for (int count = 1; count < content.Folders.Count + 1; count++) + //{ + // folders[count] = content.Folders[count - 1]; + // m_log.DebugFormat("[AAA]: Name={0}, Id={1}, Version={2}, type={3}, folderID={4}", + // folders[count].Name, folders[count].ID, folders[count].Version, folders[count].Type, folders[count].ParentID); + //} + //foreach (InventoryItemBase i in content.Items) + // m_log.DebugFormat("[AAA]: Name={0}, folderID={1}", i.Name, i.Folder); + //inv.SendBulkUpdateInventory(/*content.Folders.ToArray()*/ folders, content.Items.ToArray()); + //} + //} + //} + } + + private void RestoreSuitcaseFolderContents(IClientAPI client) + { + + } + private GridRegion MakeRegion(AgentCircuitData aCircuit) { GridRegion region = new GridRegion(); diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs index cb686e26e6..e65ad17ae6 100644 --- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs @@ -48,7 +48,7 @@ namespace OpenSim.Services.HypergridService /// and it responds to GetRootFolder requests with the ID of the /// Suitcase folder, not the actual "My Inventory" folder. /// - public class HGSuitcaseInventoryService : XInventoryService, IInventoryService + public class HGSuitcaseInventoryService1 : XInventoryService, IInventoryService { private static readonly ILog m_log = LogManager.GetLogger( @@ -61,7 +61,7 @@ namespace OpenSim.Services.HypergridService private ExpiringCache> m_SuitcaseTrees = new ExpiringCache>(); - public HGSuitcaseInventoryService(IConfigSource config, string configName) + public HGSuitcaseInventoryService1(IConfigSource config, string configName) : base(config, configName) { m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Starting with config name {0}", configName); @@ -104,11 +104,79 @@ 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) + { + if (x.parentFolderID == suitcase.folderID) + x.parentFolderID = root.folderID; + + 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 + if (f.parentFolderID == suitcase.folderID) + f.parentFolderID = root.folderID; + userInventory.Folders.Add(ConvertToOpenSim(f)); + } + + items = GetFolderItems(userID, suitcase.folderID); + if (items != null && items.Count > 0) + { + foreach (InventoryItemBase i in items) + i.Folder = root.folderID; + 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,23 +199,87 @@ 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"); + suitcase.version = root.version; + m_Database.StoreFolder(suitcase); + // Create System folders + CreateSystemFolders(principalID, suitcase.folderID); + } + else if (suitcase.version < root.version) + { + suitcase.version = root.version; m_Database.StoreFolder(suitcase); } // 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) @@ -199,6 +331,7 @@ 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); @@ -219,14 +352,37 @@ namespace OpenSim.Services.HypergridService 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); + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version); if (!IsWithinSuitcaseTree(folder.ID, root, suitcase)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name); return false; + } + if (folder.ID == root.folderID) + { + if (folder.Version <= suitcase.version) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: version {0} <= suitcase version {1}. Ignoring.", folder.Version, suitcase.version); + return false; + } + if (folder.Version <= root.version) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: version {0} <= root version {1}. Ignoring.", folder.Version, suitcase.version); + return false; + } + suitcase.version = root.version = folder.Version; + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Storing {0} type {1} version {2}", suitcase.folderName, suitcase.type, suitcase.version); + m_Database.StoreFolder(suitcase); + m_Database.StoreFolder(root); + } + + // For all others return base.UpdateFolder(folder); } @@ -301,9 +457,6 @@ namespace OpenSim.Services.HypergridService XInventoryFolder root = GetRootXFolder(items[0].Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(items[0].Owner); - if (!IsWithinSuitcaseTree(items[0].Folder, root, suitcase)) - return false; - foreach (InventoryItemBase it in items) if (it.Folder == root.folderID) { @@ -312,6 +465,9 @@ namespace OpenSim.Services.HypergridService it.Folder = suitcase.folderID; } + if (!IsWithinSuitcaseTree(items[0].Folder, root, suitcase)) + return false; + return base.MoveItems(principalID, items); } @@ -322,44 +478,57 @@ namespace OpenSim.Services.HypergridService return false; } - public override InventoryItemBase GetItem(InventoryItemBase item) + public new InventoryItemBase GetItem(InventoryItemBase item) { InventoryItemBase it = base.GetItem(item); + if (it == null) + { + 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 root = GetRootXFolder(it.Owner); XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner); - - if (it != null) + if (root == null || suitcase == 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]: Root or Suitcase are null for user {0}", + it.Owner); + return null; } + if (it.Folder == suitcase.folderID) + it.Folder = root.folderID; + + if (!IsWithinSuitcaseTree(it.Folder, root, 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 root = GetRootXFolder(f.Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner); if (f.ParentID == suitcase.folderID) f.ParentID = root.folderID; + + if (!IsWithinSuitcaseTree(f.ID, root, suitcase)) + return null; } return f; @@ -409,20 +578,22 @@ namespace OpenSim.Services.HypergridService return null; } - private void SetAsRootFolder(XInventoryFolder suitcase, UUID rootID) + private void SetAsRootFolder(XInventoryFolder suitcase, XInventoryFolder root) { - suitcase.folderID = rootID; + suitcase.version = root.version; + suitcase.folderID = root.folderID; 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,6 +618,13 @@ namespace OpenSim.Services.HypergridService } + /// + /// Return true if the folderID is a subfolder of the Suitcase or the root folder ID itself + /// + /// + /// + /// + /// private bool IsWithinSuitcaseTree(UUID folderID, XInventoryFolder root, XInventoryFolder suitcase) { List tree = new List(); @@ -463,4 +641,502 @@ namespace OpenSim.Services.HypergridService } #endregion } + + public class HGSuitcaseInventoryService : XInventoryService, IInventoryService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_HomeURL; + private IUserAccountService m_UserAccountService; + + private UserAccountCache m_Cache; + + private ExpiringCache> m_SuitcaseTrees = new ExpiringCache>(); + + public HGSuitcaseInventoryService(IConfigSource config, string configName) + : base(config, configName) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Starting with config name {0}", configName); + if (configName != string.Empty) + m_ConfigName = configName; + + if (m_Database == null) + m_log.WarnFormat("[XXX]: m_Database is null!"); + + // + // Try reading the [InventoryService] section, if it exists + // + IConfig invConfig = config.Configs[m_ConfigName]; + if (invConfig != null) + { + // realm = authConfig.GetString("Realm", realm); + string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty); + if (userAccountsDll == string.Empty) + throw new Exception("Please specify UserAccountsService in HGInventoryService configuration"); + + Object[] args = new Object[] { config }; + m_UserAccountService = ServerUtils.LoadPlugin(userAccountsDll, args); + if (m_UserAccountService == null) + throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); + + // legacy configuration [obsolete] + m_HomeURL = invConfig.GetString("ProfileServerURI", string.Empty); + // Preferred + m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL); + + m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); + } + + m_log.Debug("[HG SUITCASE INVENTORY SERVICE]: Starting..."); + } + + public override bool CreateUserInventory(UUID principalID) + { + // NOGO + return false; + } + + public override List GetInventorySkeleton(UUID principalID) + { + 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) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetRootFolder for {0}", principalID); + if (m_Database == null) + m_log.ErrorFormat("[XXX]: m_Database is NULL!"); + + // Let's find out the local root folder + XInventoryFolder root = GetRootXFolder(principalID); ; + if (root == null) + { + m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve local root folder for user {0}", principalID); + } + + // Warp! Root folder for travelers is the suitcase folder + XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); + + if (suitcase == null) + { + 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); + } + + 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); + 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); + + if (!IsWithinSuitcaseTree(folderID, suitcase)) + return new InventoryCollection(); + + coll = base.GetFolderContent(principalID, folderID); + + if (coll == null) + { + m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Something wrong with user {0}'s suitcase folder", principalID); + coll = new InventoryCollection(); + } + return coll; + } + + public override List GetFolderItems(UUID principalID, UUID folderID) + { + // 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 suitcase = GetSuitcaseXFolder(principalID); + + if (!IsWithinSuitcaseTree(folderID, suitcase)) + return new List(); + + return base.GetFolderItems(principalID, folderID); + } + + 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 suitcase = GetSuitcaseXFolder(folder.Owner); + + if (!IsWithinSuitcaseTree(folder.ParentID, suitcase)) + return false; + + // OK, it's legit + return base.AddFolder(folder); + } + + public override bool UpdateFolder(InventoryFolderBase folder) + { + XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); + + 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 suitcase = GetSuitcaseXFolder(folder.Owner); + + if (!IsWithinSuitcaseTree(folder.ID, suitcase) || !IsWithinSuitcaseTree(folder.ParentID, suitcase)) + return false; + + return base.MoveFolder(folder); + } + + public override bool DeleteFolders(UUID principalID, List folderIDs) + { + // NOGO + return false; + } + + public override bool PurgeFolder(InventoryFolderBase folder) + { + // NOGO + return false; + } + + public override bool AddItem(InventoryItemBase item) + { + // 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 suitcase = GetSuitcaseXFolder(item.Owner); + + if (!IsWithinSuitcaseTree(item.Folder, suitcase)) + return false; + + // OK, it's legit + return base.AddItem(item); + + } + + public override bool UpdateItem(InventoryItemBase item) + { + XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); + + if (!IsWithinSuitcaseTree(item.Folder, suitcase)) + return false; + + return base.UpdateItem(item); + } + + public override bool MoveItems(UUID principalID, List items) + { + // Principal is b0rked. *sigh* + + XInventoryFolder suitcase = GetSuitcaseXFolder(items[0].Owner); + + if (!IsWithinSuitcaseTree(items[0].Folder, suitcase)) + return false; + + return base.MoveItems(principalID, items); + + } + + public override bool DeleteItems(UUID principalID, List itemIDs) + { + return false; + } + + public new InventoryItemBase GetItem(InventoryItemBase item) + { + InventoryItemBase it = base.GetItem(item); + if (it == null) + { + 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 new InventoryFolderBase GetFolder(InventoryFolderBase folder) + { + InventoryFolderBase f = base.GetFolder(folder); + + if (f != null) + { + XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner); + + if (!IsWithinSuitcaseTree(f.ID, suitcase)) + return null; + } + + return f; + } + + //public List GetActiveGestures(UUID principalID) + //{ + //} + + //public int GetAssetPermissions(UUID principalID, UUID assetID) + //{ + //} + + #region Auxiliary functions + private XInventoryFolder GetXFolder(UUID userID, UUID folderID) + { + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "folderID" }, + new string[] { userID.ToString(), folderID.ToString() }); + + if (folders.Length == 0) + return null; + + return folders[0]; + } + + private XInventoryFolder GetRootXFolder(UUID principalID) + { + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "folderName", "type" }, + new string[] { principalID.ToString(), "My Inventory", ((int)AssetType.RootFolder).ToString() }); + + if (folders != null && folders.Length > 0) + return folders[0]; + return null; + } + + private XInventoryFolder GetSuitcaseXFolder(UUID principalID) + { + // Warp! Root folder for travelers + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "type" }, + new string[] { principalID.ToString(), "100" }); // This is a special folder type... + + if (folders != null && folders.Length > 0) + return folders[0]; + return null; + } + + private void SetAsRootFolder(XInventoryFolder suitcase, XInventoryFolder root) + { + suitcase.type = (short)AssetType.Folder; + } + + private List GetFolderTree(UUID folder) + { + List t = null; + if (m_SuitcaseTrees.TryGetValue(folder, out t)) + return t; + + t = GetFolderTreeRecursive(folder); + m_SuitcaseTrees.AddOrUpdate(folder, t, 120); + return t; + } + + private List GetFolderTreeRecursive(UUID root) + { + List tree = new List(); + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "parentFolderID" }, + new string[] { root.ToString() }); + + if (folders == null || (folders != null && folders.Length == 0)) + return tree; // empty tree + else + { + foreach (XInventoryFolder f in folders) + { + tree.Add(f); + tree.AddRange(GetFolderTreeRecursive(f.folderID)); + } + return tree; + } + + } + + /// + /// 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(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) + { + if (fl.folderID == folderID) return true; + else return false; + }); + + if (f == null) return false; + else return true; + } + #endregion + } + } From 7435582b7040d46675adc3795aa0e39f28c6718b Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 11:52:05 -0700 Subject: [PATCH 12/23] If an AddItem fails, try adding it to the right folder type. --- .../Framework/Scenes/Scene.Inventory.cs | 83 ++++++++++++++----- 1 file changed, 63 insertions(+), 20 deletions(-) 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. /// From 6a9f36788df8c07b76d779236b66e48cab6ae316 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 12:28:15 -0700 Subject: [PATCH 13/23] Deleted the unused and commented code from 2 commits ago. --- .../EntityTransfer/HGEntityTransferModule.cs | 242 +------ .../HGSuitcaseInventoryService.cs | 594 ------------------ 2 files changed, 1 insertion(+), 835 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index d85a996c5f..0f422ae1ce 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -411,36 +411,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #endregion - // COMPLETE FAIL - //private void RemoveRootFolderContents(IClientAPI client) - //{ - // InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing root inventory for user {0}, version {1}", client.AgentId, root.Version); - // InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - - // List keep = new List(); - // foreach (InventoryFolderBase f in content.Folders) - // { - // if (f.Type == (short)AssetType.TrashFolder || f.Type == (short)AssetType.Landmark || - // f.Type == (short)AssetType.FavoriteFolder || f.Type == (short)AssetType.CurrentOutfitFolder) - // { - // // Don't remove these because the viewer refuses to exist without them - // // and immediately sends a request to create them again, which makes things - // // very confusing in the viewer. - // // Just change their names - // f.Name = "Home " + f.Name + " (Unavailable)"; - // keep.Add(f); - // } - // else - // { - // m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); - // } - // } - - - // client.SendInventoryFolderDetails(client.AgentId, root.ID, new List(), keep, root.Version + 1, true, true); - //} - private void RemoveRootFolderContents(IClientAPI client) { // TODO tell the viewer to remove the root folder's content @@ -473,31 +443,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer foreach (InventoryItemBase it in content.Items) it.Name = it.Name + " (Unavailable)"; ; - // next, add the subfolders and items of the keep folders - //foreach (InventoryFolderBase f in keep) - //{ - // InventoryCollection c = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, f.ID); - // foreach (InventoryFolderBase sf in c.Folders) - // { - // m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); - // fids.Add(sf.ID); - // } - // foreach (InventoryItemBase it in c.Items) - // iids.Add(it.ID); - //} - - //inv.SendRemoveInventoryFolders(fids.ToArray()); - - // Increase the version number - //root.Version += 1; - //m_Scenes[0].InventoryService.UpdateFolder(root); - //foreach (InventoryFolderBase f in keep) - //{ - // f.Version += 1; - // m_Scenes[0].InventoryService.UpdateFolder(f); - //} - - // Send the new names and versions + // Send the new names inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray()); } @@ -505,133 +451,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } - private void RemoveRootFolderContents2(IClientAPI client) - { - // TODO tell the viewer to remove the root folder's content - if (client is IClientCore) - { - IClientCore core = (IClientCore)client; - IClientInventory inv; - - if (core.TryGet(out inv)) - { - 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.Name); - InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - List fids = new List(); - List iids = new List(); - List keep = new List(); - - foreach (InventoryFolderBase f in content.Folders) - { - if (f.Type == (short)AssetType.TrashFolder || f.Type == (short)AssetType.Landmark || - f.Type == (short)AssetType.FavoriteFolder || f.Type == (short)AssetType.CurrentOutfitFolder) - { - // Don't remove these because the viewer refuses to exist without them - // and immediately sends a request to create them again, which makes things - // very confusing in the viewer. - // Just change their names - f.Name = "Home " + f.Name + " (Unavailable)"; - keep.Add(f); - } - else - { - m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); - fids.Add(f.ID); - } - } - - foreach (InventoryItemBase it in content.Items) - iids.Add(it.ID); - - // next, add the subfolders and items of the keep folders - foreach (InventoryFolderBase f in keep) - { - InventoryCollection c = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, f.ID); - foreach (InventoryFolderBase sf in c.Folders) - { - m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); - fids.Add(sf.ID); - } - foreach (InventoryItemBase it in c.Items) - iids.Add(it.ID); - } - - inv.SendRemoveInventoryFolders(fids.ToArray()); - inv.SendRemoveInventoryItems(iids.ToArray()); - - // Increase the version number - root.Version += 1; - m_Scenes[0].InventoryService.UpdateFolder(root); - //foreach (InventoryFolderBase f in keep) - //{ - // f.Version += 1; - // m_Scenes[0].InventoryService.UpdateFolder(f); - //} - - // Send the new names and versions - inv.SendBulkUpdateInventory(keep.ToArray(), new InventoryItemBase[0]); - - } - } - } - } - private void RemoveSuitcaseFolderContents(IClientAPI client) { - return; - - //// TODO tell the viewer to remove the suitcase folder's content - //if (client is IClientCore) - //{ - // IClientCore core = (IClientCore)client; - // IClientInventory inv; - - // if (core.TryGet(out inv)) - // { - // InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - // if (root != null) - // { - // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing suitcase inventory for user {0}", client.Name); - // InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - // List fids = new List(); - // List iids = new List(); - - // if (content.Folders.Count == 0) - // m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: no subfolders???"); - // foreach (InventoryFolderBase f in content.Folders) - // { - // m_log.DebugFormat("[RRR]: Name={0}, Version={1}, Type={2}, PfolderID={3}", f.Name, f.Version, f.Type, f.ParentID); - // fids.Add(f.ID); - // } - - // foreach (InventoryItemBase it in content.Items) - // iids.Add(it.ID); - - // inv.SendRemoveInventoryFolders(fids.ToArray()); - // inv.SendRemoveInventoryItems(iids.ToArray()); - - // // Increase the version number - // root.Version += 1; - // m_Scenes[0].InventoryService.UpdateFolder(root); - // } - // } - //} } private void RestoreRootFolderContents(IClientAPI client) { - // This works! - //InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - //client.SendBulkUpdateInventory(root); - - // SORTA KINDA some items are missing... - //InventoryCollection userInventory = m_Scenes[0].InventoryService.GetUserInventory(client.AgentId); - //InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - //client.SendBulkUpdateInventory(root); - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root folder"); if (client is IClientCore) { @@ -646,75 +471,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); } } - - // ATTEMPT # 3 -- STILL DOESN'T WORK! - //if (client is IClientCore) - //{ - // IClientCore core = (IClientCore)client; - // IClientInventory inv; - - // if (core.TryGet(out inv)) - // { - // InventoryCollection userInventory = m_Scenes[0].InventoryService.GetUserInventory(client.AgentId); - // if (userInventory != null) - // { - // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory for user {0}", client.AgentId); - // foreach (InventoryFolderBase f in userInventory.Folders) - // m_log.DebugFormat("[AAA]: FOLDER {0} {1} {2} {3} {4}", f.Name, f.Type, f.Version, f.ID, f.ParentID); - // foreach (InventoryItemBase f in userInventory.Items) - // m_log.DebugFormat("[AAA]: ITEM {0} {1} {2}", f.Name, f.ID, f.Folder); - // inv.SendBulkUpdateInventory(userInventory.Folders.ToArray(), userInventory.Items.ToArray()); - // } - // else - // m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve inventory for user {0}", client.AgentId); - // } - //} - - - // ATTEMPT #2 -- BETTER THAN 1, BUT STILL DOES NOT WORK WELL - //if (client is IClientCore) - //{ - // IClientCore core = (IClientCore)client; - // IClientInventory inv; - - // if (core.TryGet(out inv)) - // { - // List skel = m_Scenes[0].InventoryService.GetInventorySkeleton(client.AgentId); - // if (skel != null) - // { - // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory for user {0}", client.AgentId); - // foreach (InventoryFolderBase f in skel) - // m_log.DebugFormat("[AAA]: {0} {1} {2} {3} {4}", f.Name, f.Type, f.Version, f.ID, f.ParentID); - // inv.SendBulkUpdateInventory(skel.ToArray(), new InventoryItemBase[0]); - // } - // else - // m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve skeleton for user {0}", client.AgentId); - - // ATTEMPT #1 -- DOES NOT WORK - //InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - //if (root != null) - //{ - //InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - //InventoryFolderBase[] folders = new InventoryFolderBase[content.Folders.Count + 1]; - //m_log.DebugFormat("[AAA]: Folder name {0}, id {1}, version {2}, parent {3}", root.Name, root.ID, root.Version, root.ParentID); - //folders[0] = root; - //for (int count = 1; count < content.Folders.Count + 1; count++) - //{ - // folders[count] = content.Folders[count - 1]; - // m_log.DebugFormat("[AAA]: Name={0}, Id={1}, Version={2}, type={3}, folderID={4}", - // folders[count].Name, folders[count].ID, folders[count].Version, folders[count].Type, folders[count].ParentID); - //} - //foreach (InventoryItemBase i in content.Items) - // m_log.DebugFormat("[AAA]: Name={0}, folderID={1}", i.Name, i.Folder); - //inv.SendBulkUpdateInventory(/*content.Folders.ToArray()*/ folders, content.Items.ToArray()); - //} - //} - //} } private void RestoreSuitcaseFolderContents(IClientAPI client) { - } private GridRegion MakeRegion(AgentCircuitData aCircuit) diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs index e65ad17ae6..b6ec558b80 100644 --- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs @@ -48,600 +48,6 @@ namespace OpenSim.Services.HypergridService /// and it responds to GetRootFolder requests with the ID of the /// Suitcase folder, not the actual "My Inventory" folder. /// - public class HGSuitcaseInventoryService1 : XInventoryService, IInventoryService - { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - private string m_HomeURL; - private IUserAccountService m_UserAccountService; - - private UserAccountCache m_Cache; - - private ExpiringCache> m_SuitcaseTrees = new ExpiringCache>(); - - public HGSuitcaseInventoryService1(IConfigSource config, string configName) - : base(config, configName) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Starting with config name {0}", configName); - if (configName != string.Empty) - m_ConfigName = configName; - - if (m_Database == null) - m_log.WarnFormat("[XXX]: m_Database is null!"); - - // - // Try reading the [InventoryService] section, if it exists - // - IConfig invConfig = config.Configs[m_ConfigName]; - if (invConfig != null) - { - // realm = authConfig.GetString("Realm", realm); - string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty); - if (userAccountsDll == string.Empty) - throw new Exception("Please specify UserAccountsService in HGInventoryService configuration"); - - Object[] args = new Object[] { config }; - m_UserAccountService = ServerUtils.LoadPlugin(userAccountsDll, args); - if (m_UserAccountService == null) - throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); - - // legacy configuration [obsolete] - m_HomeURL = invConfig.GetString("ProfileServerURI", string.Empty); - // Preferred - m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL); - - m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); - } - - m_log.Debug("[HG SUITCASE INVENTORY SERVICE]: Starting..."); - } - - public override bool CreateUserInventory(UUID principalID) - { - // NOGO - return false; - } - - public override List GetInventorySkeleton(UUID principalID) - { - 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) - { - if (x.parentFolderID == suitcase.folderID) - x.parentFolderID = root.folderID; - - 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 - if (f.parentFolderID == suitcase.folderID) - f.parentFolderID = root.folderID; - userInventory.Folders.Add(ConvertToOpenSim(f)); - } - - items = GetFolderItems(userID, suitcase.folderID); - if (items != null && items.Count > 0) - { - foreach (InventoryItemBase i in items) - i.Folder = root.folderID; - 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) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetRootFolder for {0}", principalID); - if (m_Database == null) - m_log.ErrorFormat("[XXX]: m_Database is NULL!"); - - // Let's find out the local root folder - XInventoryFolder root = GetRootXFolder(principalID); ; - if (root == null) - { - m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve local root folder for user {0}", principalID); - } - - // Warp! Root folder for travelers is the suitcase folder - XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); - - if (suitcase == null) - { - 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"); - suitcase.version = root.version; - m_Database.StoreFolder(suitcase); - - // Create System folders - CreateSystemFolders(principalID, suitcase.folderID); - } - else if (suitcase.version < root.version) - { - suitcase.version = root.version; - m_Database.StoreFolder(suitcase); - } - - // Now let's change the folder ID to match that of the real root folder - 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); - 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)) - 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); - } - if (coll == null) - { - m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Something wrong with user {0}'s suitcase folder", principalID); - coll = new InventoryCollection(); - } - return coll; - } - - public override List GetFolderItems(UUID principalID, UUID folderID) - { - // 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)) - return new List(); - - return base.GetFolderItems(principalID, folderID); - } - - 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)) - 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 override bool UpdateFolder(InventoryFolderBase folder) - { - XInventoryFolder root = GetRootXFolder(folder.Owner); - XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); - - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version); - if (!IsWithinSuitcaseTree(folder.ID, root, suitcase)) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name); - return false; - } - - if (folder.ID == root.folderID) - { - if (folder.Version <= suitcase.version) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: version {0} <= suitcase version {1}. Ignoring.", folder.Version, suitcase.version); - return false; - } - if (folder.Version <= root.version) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: version {0} <= root version {1}. Ignoring.", folder.Version, suitcase.version); - return false; - } - suitcase.version = root.version = folder.Version; - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Storing {0} type {1} version {2}", suitcase.folderName, suitcase.type, suitcase.version); - m_Database.StoreFolder(suitcase); - m_Database.StoreFolder(root); - } - - // 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)) - 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); - } - - public override bool DeleteFolders(UUID principalID, List folderIDs) - { - // NOGO - return false; - } - - public override bool PurgeFolder(InventoryFolderBase folder) - { - // NOGO - return false; - } - - public override bool AddItem(InventoryItemBase item) - { - // 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)) - 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)) - return false; - - return base.UpdateItem(item); - } - - public override bool MoveItems(UUID principalID, List items) - { - // Principal is b0rked. *sigh* - - XInventoryFolder root = GetRootXFolder(items[0].Owner); - XInventoryFolder suitcase = GetSuitcaseXFolder(items[0].Owner); - - 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; - } - - if (!IsWithinSuitcaseTree(items[0].Folder, root, suitcase)) - return false; - - return base.MoveItems(principalID, items); - - } - - // Let these pass. Use inherited methods. - public override bool DeleteItems(UUID principalID, List itemIDs) - { - return false; - } - - public new InventoryItemBase GetItem(InventoryItemBase item) - { - InventoryItemBase it = base.GetItem(item); - if (it == null) - { - 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 root = GetRootXFolder(it.Owner); - XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner); - if (root == null || suitcase == null) - { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Root or Suitcase are null for user {0}", - it.Owner); - return null; - } - - if (it.Folder == suitcase.folderID) - it.Folder = root.folderID; - - if (!IsWithinSuitcaseTree(it.Folder, root, 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 new InventoryFolderBase GetFolder(InventoryFolderBase folder) - { - InventoryFolderBase f = base.GetFolder(folder); - - if (f != null) - { - XInventoryFolder root = GetRootXFolder(f.Owner); - XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner); - if (f.ParentID == suitcase.folderID) - f.ParentID = root.folderID; - - if (!IsWithinSuitcaseTree(f.ID, root, suitcase)) - return null; - } - - return f; - } - - //public List GetActiveGestures(UUID principalID) - //{ - //} - - //public int GetAssetPermissions(UUID principalID, UUID assetID) - //{ - //} - - #region Auxiliary functions - private XInventoryFolder GetXFolder(UUID userID, UUID folderID) - { - XInventoryFolder[] folders = m_Database.GetFolders( - new string[] { "agentID", "folderID" }, - new string[] { userID.ToString(), folderID.ToString() }); - - if (folders.Length == 0) - return null; - - return folders[0]; - } - - private XInventoryFolder GetRootXFolder(UUID principalID) - { - XInventoryFolder[] folders = m_Database.GetFolders( - new string[] { "agentID", "folderName", "type" }, - new string[] { principalID.ToString(), "My Inventory", ((int)AssetType.RootFolder).ToString() }); - - if (folders != null && folders.Length > 0) - return folders[0]; - return null; - } - - private XInventoryFolder GetSuitcaseXFolder(UUID principalID) - { - // Warp! Root folder for travelers - XInventoryFolder[] folders = m_Database.GetFolders( - new string[] { "agentID", "type" }, - new string[] { principalID.ToString(), "100" }); // This is a special folder type... - - if (folders != null && folders.Length > 0) - return folders[0]; - return null; - } - - private void SetAsRootFolder(XInventoryFolder suitcase, XInventoryFolder root) - { - suitcase.version = root.version; - suitcase.folderID = root.folderID; - suitcase.parentFolderID = UUID.Zero; - suitcase.type = (short)AssetType.Folder; - } - - private List GetFolderTree(UUID folder) - { - List t = null; - if (m_SuitcaseTrees.TryGetValue(folder, out t)) - return t; - - t = GetFolderTreeRecursive(folder); - m_SuitcaseTrees.AddOrUpdate(folder, t, 120); - return t; - } - - private List GetFolderTreeRecursive(UUID root) - { - List tree = new List(); - XInventoryFolder[] folders = m_Database.GetFolders( - new string[] { "parentFolderID" }, - new string[] { root.ToString() }); - - if (folders == null || (folders != null && folders.Length == 0)) - return tree; // empty tree - else - { - foreach (XInventoryFolder f in folders) - { - tree.Add(f); - tree.AddRange(GetFolderTreeRecursive(f.folderID)); - } - return tree; - } - - } - - /// - /// Return true if the folderID is a subfolder of the Suitcase or the root folder ID itself - /// - /// - /// - /// - /// - private bool IsWithinSuitcaseTree(UUID folderID, XInventoryFolder root, 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.AddRange(GetFolderTree(suitcase.folderID)); - XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl) - { - if (fl.folderID == folderID) return true; - else return false; - }); - - if (f == null) return false; - else return true; - } - #endregion - } - public class HGSuitcaseInventoryService : XInventoryService, IInventoryService { private static readonly ILog m_log = From 627efc172bda961f888dd3191fd8e1c4885f46e3 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 6 Apr 2012 20:32:39 +0100 Subject: [PATCH 14/23] Make llGetMass() return total mass of object when called on root prim. As per http://lslwiki.net/lslwiki/wakka.php?wakka=llGetMass Aims to resolve http://opensimulator.org/mantis/view.php?id=5954 --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 8d25a62cb8..43b66f46e3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2907,7 +2907,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Float llGetMass() { m_host.AddScriptLPS(1); - return m_host.GetMass(); + if (m_host.IsRoot) + return m_host.ParentGroup.GetMass(); + else + return m_host.GetMass(); } public void llCollisionFilter(string name, string id, int accept) From c3a8c00ce0e60b0988fc0d62712e896e5c3e1ac8 Mon Sep 17 00:00:00 2001 From: Talun Date: Fri, 6 Apr 2012 19:11:09 +0100 Subject: [PATCH 15/23] Addition of missing constants for llGetObjectDetails including for Mantis 5502 Signed-off-by: nebadon --- .../Shared/Api/Implementation/LSL_Api.cs | 72 +++++++++++++++++++ .../Shared/Api/Runtime/LSL_Constants.cs | 10 +++ 2 files changed, 82 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 43b66f46e3..a046f2951a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10333,6 +10333,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; } } @@ -10370,6 +10399,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); From f2903db39009c7e62f6a07c545183b9588bff775 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 6 Apr 2012 21:14:19 +0100 Subject: [PATCH 16/23] For llGetMass(), return the mass of the avatar is the object is attached. As per http://lslwiki.net/lslwiki/wakka.php?wakka=llGetMass This is the mass as used by the physics engine (ODE or Bullet). --- .../Region/Framework/Scenes/ScenePresence.cs | 16 +++++++++++ .../Shared/Api/Implementation/LSL_Api.cs | 27 ++++++++++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) 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 43b66f46e3..17f5a64149 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2907,10 +2907,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Float llGetMass() { m_host.AddScriptLPS(1); - if (m_host.IsRoot) - return m_host.ParentGroup.GetMass(); + + if (m_host.ParentGroup.IsAttachment) + { + ScenePresence attachedAvatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar); + + if (attachedAvatar != null) + { + return attachedAvatar.GetMass(); + } + else + { + return 0; + } + } else - return m_host.GetMass(); + { + if (m_host.IsRoot) + { + return m_host.ParentGroup.GetMass(); + } + else + { + return m_host.GetMass(); + } + } } public void llCollisionFilter(string name, string id, int accept) From 3af1cd65f91db87778096196bfd985dc48c72d87 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 6 Apr 2012 22:41:35 +0100 Subject: [PATCH 17/23] Fix llGetLinkPrimParams for PRIM_POS_LOCAL for child prims whether in scene or attachments. Return relative position to root prim rather than 0,0,0. Should fix same issue with llGetLocalPos() http://opensimulator.org/mantis/view.php?id=5951 --- .../Framework/Scenes/SceneObjectPart.cs | 16 +++++++++++--- .../Shared/Api/Implementation/LSL_Api.cs | 21 ++++++++++--------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 9e65f5d5fe..5ec0ed9aa5 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 @@ -1112,6 +1114,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; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index a85a36e839..ad73f4749e 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); + + Vector3 pos; + if (part.ParentID == 0) { - return new LSL_Vector(part.AbsolutePosition.X, - part.AbsolutePosition.Y, - part.AbsolutePosition.Z); + pos = part.AbsolutePosition; } else { - if (m_host.IsRoot) + if (part.IsRoot) { - 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.OffsetPosition; } } + +// 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) From 4a58d4c5a4e7e405448113a0efd5c34349eed7b5 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 6 Apr 2012 23:36:13 +0100 Subject: [PATCH 18/23] refactor: Use clearer part.ParentGroup.IsAttachment in LSL_Api.GetPartLocalPos() --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index ad73f4749e..021b3523a4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2025,19 +2025,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api Vector3 pos; - if (part.ParentID == 0) + if (!part.IsRoot) { - pos = part.AbsolutePosition; + pos = part.OffsetPosition; } else { - if (part.IsRoot) + if (part.ParentGroup.IsAttachment) { pos = part.AttachedPos; } else { - pos = part.OffsetPosition; + pos = part.AbsolutePosition; } } From 33e91f1088ce055fa52f34cabc2d211fcc587b5f Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 6 Apr 2012 23:43:03 +0100 Subject: [PATCH 19/23] Implement PRIM_POS_LOCAL on llSetPrimitiveParams() and other prim params LSL functions. This is the same as PRIM_POSITION --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 021b3523a4..8223d95484 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7171,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; From 70b5a2dacede6b44327856970185471adf808f3c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 6 Apr 2012 23:49:23 +0100 Subject: [PATCH 20/23] refactor: Eliminate unnecessary SOP.m_physActor --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 5ec0ed9aa5..2fcce1c520 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -161,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. @@ -268,7 +260,6 @@ namespace OpenSim.Region.Framework.Scenes private bool m_passTouches; - private PhysicsActor m_physActor; protected Vector3 m_acceleration; protected Vector3 m_angularVelocity; From 7d8bb33c5b2420d4e744269f67a25dd2b9746a35 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 7 Apr 2012 00:33:02 +0100 Subject: [PATCH 21/23] Store FromItemID for attachments once on SOG instead of on every SOP and only ever using the root part entry. This eliminates some pointless memory use. --- .../ClientStack/Linden/UDP/LLClientView.cs | 2 +- .../Avatar/Attachments/AttachmentsModule.cs | 20 ++++++------- .../Tests/AttachmentsModuleTests.cs | 5 ++-- .../InventoryAccess/InventoryAccessModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- .../Framework/Scenes/SceneObjectGroup.cs | 28 ++++++++----------- .../Framework/Scenes/SceneObjectPart.cs | 2 -- .../Shared/Api/Implementation/LSL_Api.cs | 2 +- 8 files changed, 29 insertions(+), 34 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 9395233262..619ef14452 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4957,7 +4957,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim if (data.ParentGroup.IsAttachment) { - update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID); + update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.ParentGroup.FromItemID); update.State = (byte)((data.ParentGroup.AttachmentPoint % 16) * 16 + (data.ParentGroup.AttachmentPoint / 16)); } else diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 7086e6c331..faa413e811 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -239,7 +239,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // At the moment we can only deal with a single attachment if (attachments.Count != 0) { - UUID oldAttachmentItemID = attachments[0].GetFromItemID(); + UUID oldAttachmentItemID = attachments[0].FromItemID; if (oldAttachmentItemID != UUID.Zero) DetachSingleAttachmentToInvInternal(sp, oldAttachmentItemID); @@ -250,7 +250,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } // Add the new attachment to inventory if we don't already have it. - UUID newAttachmentItemID = group.GetFromItemID(); + UUID newAttachmentItemID = group.FromItemID; if (newAttachmentItemID == UUID.Zero) newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; @@ -285,7 +285,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments List existingAttachments = sp.GetAttachments(); foreach (SceneObjectGroup so in existingAttachments) { - if (so.GetFromItemID() == itemID) + if (so.FromItemID == itemID) { alreadyOn = true; break; @@ -342,7 +342,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (so.AttachedAvatar != sp.UUID) return; - UUID inventoryID = so.GetFromItemID(); + UUID inventoryID = so.FromItemID; // m_log.DebugFormat( // "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}", @@ -359,9 +359,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); sp.RemoveAttachment(so); + so.FromItemID = UUID.Zero; SceneObjectPart rootPart = so.RootPart; - rootPart.FromItemID = UUID.Zero; so.AbsolutePosition = sp.AbsolutePosition; so.AttachedAvatar = UUID.Zero; rootPart.SetParentLocalId(0); @@ -475,7 +475,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); - InventoryItemBase item = new InventoryItemBase(grp.GetFromItemID(), sp.UUID); + InventoryItemBase item = new InventoryItemBase(grp.FromItemID, sp.UUID); item = m_scene.InventoryService.GetItem(item); if (item != null) @@ -647,7 +647,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments item.CreationDate = Util.UnixTimeSinceEpoch(); // sets itemID so client can show item as 'attached' in inventory - grp.SetFromItemID(item.ID); + grp.FromItemID = item.ID; if (m_scene.AddInventoryItem(item)) { @@ -683,7 +683,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (entity is SceneObjectGroup) { group = (SceneObjectGroup)entity; - if (group.GetFromItemID() == itemID) + if (group.FromItemID == itemID) { m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); sp.RemoveAttachment(group); @@ -889,7 +889,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // Calls attach with a Zero position if (AttachObject(sp, part.ParentGroup, AttachmentPt, false)) { - m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); + m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.FromItemID, remoteClient.AgentId); // Save avatar attachment information m_log.Debug( @@ -912,7 +912,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); if (sp != null && group != null) - DetachSingleAttachmentToInv(sp, group.GetFromItemID()); + DetachSingleAttachmentToInv(sp, group.FromItemID); } private void Client_OnDetachAttachmentIntoInv(UUID itemID, IClientAPI remoteClient) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 86cfb324dc..bfe5e4a37f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -120,8 +120,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(attSo.IsTemporary, Is.False); // Check item status - Assert.That(m_presence.Appearance.GetAttachpoint( - attSo.GetFromItemID()), Is.EqualTo((int)AttachmentPoint.Chest)); + Assert.That( + m_presence.Appearance.GetAttachpoint(attSo.FromItemID), + Is.EqualTo((int)AttachmentPoint.Chest)); } [Test] diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 4dd89d2e88..88c21afc59 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -1008,7 +1008,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess rootPart.TrimPermissions(); if (isAttachment) - so.SetFromItemID(item.ID); + so.FromItemID = item.ID; } return true; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index d8cac66637..e488fe151a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2566,7 +2566,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup grp = sceneObject; m_log.DebugFormat( - "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.GetFromItemID(), grp.UUID); + "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.FromItemID, grp.UUID); m_log.DebugFormat( "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 87fdc41d73..3586e95762 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -571,7 +571,9 @@ namespace OpenSim.Region.Framework.Scenes set { m_LoopSoundSlavePrims = value; } } - // The UUID for the Region this Object is in. + /// + /// The UUID for the region this object is in. + /// public UUID RegionUUID { get @@ -584,6 +586,11 @@ namespace OpenSim.Region.Framework.Scenes } } + /// + /// The item ID that this object was rezzed from, if applicable. + /// + public UUID FromItemID { get; set; } + #endregion // ~SceneObjectGroup() @@ -646,18 +653,6 @@ namespace OpenSim.Region.Framework.Scenes } } - public void SetFromItemID(UUID AssetId) - { - SceneObjectPart[] parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - parts[i].FromItemID = AssetId; - } - - public UUID GetFromItemID() - { - return m_rootPart.FromItemID; - } - /// /// Hooks this object up to the backup event so that it is persisted to the database when the update thread executes. /// @@ -2687,6 +2682,7 @@ namespace OpenSim.Region.Framework.Scenes { m_rootPart.AttachedPos = pos; } + if (RootPart.GetStatusSandbox()) { if (Util.GetDistanceTo(RootPart.StatusSandboxPos, pos) > 10) @@ -2697,8 +2693,8 @@ namespace OpenSim.Region.Framework.Scenes ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); } } - AbsolutePosition = pos; + AbsolutePosition = pos; HasGroupChanged = true; } @@ -3270,7 +3266,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual string ExtraToXmlString() { - return "" + GetFromItemID().ToString() + ""; + return "" + FromItemID.ToString() + ""; } public virtual void ExtraFromXmlString(string xmlstr) @@ -3282,7 +3278,7 @@ namespace OpenSim.Region.Framework.Scenes UUID uuid = UUID.Zero; UUID.TryParse(id, out uuid); - SetFromItemID(uuid); + FromItemID = uuid; } #endregion diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 2fcce1c520..fffaa061f6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -181,8 +181,6 @@ namespace OpenSim.Region.Framework.Scenes public uint TimeStampLastActivity; // Will be used for AutoReturn public uint TimeStampTerse; - - public UUID FromItemID; public UUID FromFolderID; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 8223d95484..291f52e496 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3080,7 +3080,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api SceneObjectPart host = (SceneObjectPart)o; SceneObjectGroup grp = host.ParentGroup; - UUID itemID = grp.GetFromItemID(); + UUID itemID = grp.FromItemID; ScenePresence presence = World.GetScenePresence(host.OwnerID); IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; From cce760dbfcd375a700e38b8279b0c19c5624e720 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 7 Apr 2012 00:40:55 +0100 Subject: [PATCH 22/23] Rather than having a FromFolderID property on every single prim and only ever using the root prim one, store on SOG instead. This reduces pointless memory usage. --- .../ClientStack/Linden/UDP/LLClientView.cs | 2 +- .../InventoryAccess/InventoryAccessModule.cs | 6 +++--- .../Framework/Scenes/SceneObjectGroup.cs | 19 +++++++++++++++---- .../Framework/Scenes/SceneObjectPart.cs | 2 -- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 619ef14452..ae5cbfff55 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -4271,7 +4271,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP block.OwnerID = sop.OwnerID; block.ItemID = sop.FromUserInventoryItemID; - block.FolderID = UUID.Zero; // sop.FromFolderID ?? + block.FolderID = UUID.Zero; // sog.FromFolderID ?? block.FromTaskID = UUID.Zero; // ??? block.InventorySerial = (short)sop.InventorySerial; diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 88c21afc59..8171487545 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -654,9 +654,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) { - if (so.RootPart.FromFolderID != UUID.Zero && userID == remoteClient.AgentId) + if (so.FromFolderID != UUID.Zero && userID == remoteClient.AgentId) { - InventoryFolderBase f = new InventoryFolderBase(so.RootPart.FromFolderID, userID); + InventoryFolderBase f = new InventoryFolderBase(so.FromFolderID, userID); folder = m_Scene.InventoryService.GetFolder(f); } } @@ -962,7 +962,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess rootPart.SalePrice = item.SalePrice; } - rootPart.FromFolderID = item.Folder; + so.FromFolderID = item.Folder; // Console.WriteLine("rootPart.OwnedID {0}, item.Owner {1}, item.CurrentPermissions {2:X}", // rootPart.OwnerID, item.Owner, item.CurrentPermissions); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 3586e95762..17f3be7d83 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -586,10 +586,21 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// The item ID that this object was rezzed from, if applicable. - /// - public UUID FromItemID { get; set; } + /// + /// The item ID that this object was rezzed from, if applicable. + /// + /// + /// If not applicable will be UUID.Zero + /// + public UUID FromItemID { get; set; } + + /// + /// The folder ID that this object was rezzed from, if applicable. + /// + /// + /// If not applicable will be UUID.Zero + /// + public UUID FromFolderID { get; set; } #endregion diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index fffaa061f6..046553ba6a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -182,8 +182,6 @@ namespace OpenSim.Region.Framework.Scenes public uint TimeStampTerse; - public UUID FromFolderID; - public int STATUS_ROTATE_X; public int STATUS_ROTATE_Y; From 9637e509567efe512d4b29ea925c10011cdbe99e Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Apr 2012 20:34:31 -0700 Subject: [PATCH 23/23] Moved the inventory manipulation from HGEntityTransferModule to HGInventoryAccessModule where it belongs. They need to exchange some events, so added those to EventManager. Those events (TeleportStart and TeleportFail) are nice to have anyway. --- .../EntityTransfer/EntityTransferModule.cs | 8 +- .../EntityTransfer/HGEntityTransferModule.cs | 149 +---------------- .../HGInventoryAccessModule.cs | 152 +++++++++++++++++- .../Region/Framework/Scenes/EventManager.cs | 49 ++++++ 4 files changed, 208 insertions(+), 150 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 86e10d491f..fa9cd551ad 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -561,12 +561,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // Finally, kill the agent we just created at the destination. m_aScene.SimulationService.CloseAgent(finalDestination, sp.UUID); + sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout); } protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason, out bool logout) { logout = false; - return m_aScene.SimulationService.CreateAgent(finalDestination, agentCircuit, teleportFlags, out reason); + bool success = m_aScene.SimulationService.CreateAgent(finalDestination, agentCircuit, teleportFlags, out reason); + + if (success) + sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout); + + return success; } protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 0f422ae1ce..7f9175d2fc 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -51,8 +51,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer private bool m_Initialized = false; - private bool m_RestrictInventoryAccessAbroad = false; - private GatekeeperServiceConnector m_GatekeeperConnector; #region ISharedRegionModule @@ -71,10 +69,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (name == Name) { InitialiseCommon(source); - IConfig transferConfig = source.Configs["HGEntityTransferModule"]; - if (transferConfig != null) - m_RestrictInventoryAccessAbroad = transferConfig.GetBoolean("RestrictInventoryAccessAbroad", false); - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); } } @@ -94,44 +88,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer client.OnTeleportHomeRequest += TeleportHome; client.OnTeleportLandmarkRequest += RequestTeleportLandmark; client.OnConnectionClosed += new Action(OnConnectionClosed); - client.OnCompleteMovementToRegion += new Action(OnCompleteMovementToRegion); } - protected void OnCompleteMovementToRegion(IClientAPI client, bool arg2) - { - // HACK HACK -- just seeing how the viewer responds - // Let's send the Suitcase or the real root folder folder for incoming HG agents - // Visiting agents get their suitcase contents; incoming local users get their real root folder's content - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: OnCompleteMovementToRegion of user {0}", client.AgentId); - object sp = null; - if (client.Scene.TryGetScenePresence(client.AgentId, out sp)) - { - if (sp is ScenePresence) - { - AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId); - if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) - { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: ViaHGLogin"); - if (m_RestrictInventoryAccessAbroad) - { - 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); - } - } - } - } - } - } - - public override void RegionLoaded(Scene scene) { base.RegionLoaded(scene); @@ -141,12 +99,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService); m_Initialized = true; - scene.AddCommand( - "HG", this, "send inventory", - "send inventory", - "Don't use this", - HandleSendInventory); - } } @@ -219,21 +171,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer bool success = connector.LoginAgentToGrid(agentCircuit, reg, finalDestination, out reason); logout = success; // flag for later logout from this grid; this is an HG TP - if (success && m_RestrictInventoryAccessAbroad) - { - 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); - } - } + if (success) + sp.Scene.EventManager.TriggerTeleportStart(sp.ControllingClient, reg, finalDestination, teleportFlags, logout); return success; } @@ -244,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } - return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason); + return base.CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout); } public override void TeleportHome(UUID id, IClientAPI client) @@ -348,15 +287,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } - protected override void Fail(ScenePresence sp, GridRegion finalDestination, bool logout) - { - base.Fail(sp, finalDestination, logout); - if (logout && m_RestrictInventoryAccessAbroad) - { - RestoreRootFolderContents(sp.ControllingClient); - } - } - #endregion #region IUserAgentVerificationModule @@ -411,71 +341,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #endregion - private void RemoveRootFolderContents(IClientAPI client) - { - // TODO tell the viewer to remove the root folder's content - if (client is IClientCore) - { - IClientCore core = (IClientCore)client; - IClientInventory inv; - - if (core.TryGet(out inv)) - { - 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.Name); - InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - List fids = new List(); - List iids = new List(); - List keep = new List(); - - foreach (InventoryFolderBase f in content.Folders) - { - 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) - 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; - IClientInventory inv; - - if (core.TryGet(out inv)) - { - InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); - - inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); - } - } - } - - private void RestoreSuitcaseFolderContents(IClientAPI client) - { - } private GridRegion MakeRegion(AgentCircuitData aCircuit) { @@ -494,13 +359,5 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return region; } - protected void HandleSendInventory(string module, string[] cmd) - { - m_Scenes[0].ForEachClient(delegate(IClientAPI client) - { - RestoreRootFolderContents(client); - }); - } - } } diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index d2fe3888fa..a71584a91b 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.Reflection; using OpenSim.Framework; +using OpenSim.Framework.Client; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Connectors.Hypergrid; @@ -57,6 +58,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess private string m_HomeURI; private bool m_OutboundPermission; private string m_ThisGatekeeper; + private bool m_RestrictInventoryAccessAbroad; // private bool m_Initialized = false; @@ -90,6 +92,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI); m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); + m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", false); } else m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); @@ -105,13 +108,79 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess base.AddRegion(scene); m_assMapper = new HGAssetMapper(scene, m_HomeURI); scene.EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem; - + scene.EventManager.OnTeleportStart += TeleportStart; + scene.EventManager.OnTeleportFail += TeleportFail; } #endregion #region Event handlers + protected override void OnNewClient(IClientAPI client) + { + base.OnNewClient(client); + client.OnCompleteMovementToRegion += new Action(OnCompleteMovementToRegion); + } + + protected void OnCompleteMovementToRegion(IClientAPI client, bool arg2) + { + //m_log.DebugFormat("[HG INVENTORY ACCESS MODULE]: OnCompleteMovementToRegion of user {0}", client.Name); + object sp = null; + if (client.Scene.TryGetScenePresence(client.AgentId, out sp)) + { + if (sp is ScenePresence) + { + AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId); + if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) + { + if (m_RestrictInventoryAccessAbroad) + { + IUserManagement uMan = m_Scene.RequestModuleInterface(); + if (uMan.IsLocalGridUser(client.AgentId)) + ProcessInventoryForComingHome(client); + else + ProcessInventoryForArriving(client); + } + } + } + } + } + + protected void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout) + { + if (gridLogout && m_RestrictInventoryAccessAbroad) + { + IUserManagement uMan = m_Scene.RequestModuleInterface(); + if (uMan != null && uMan.IsLocalGridUser(client.AgentId)) + { + // local grid user + ProcessInventoryForHypergriding(client); + } + else + { + // Foreigner + ProcessInventoryForLeaving(client); + } + } + + } + + protected void TeleportFail(IClientAPI client, bool gridLogout) + { + if (gridLogout && m_RestrictInventoryAccessAbroad) + { + IUserManagement uMan = m_Scene.RequestModuleInterface(); + if (uMan.IsLocalGridUser(client.AgentId)) + { + ProcessInventoryForComingHome(client); + } + else + { + ProcessInventoryForArriving(client); + } + } + } + public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel) { string userAssetServer = string.Empty; @@ -236,8 +305,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return false; } - #endregion - protected override InventoryItemBase GetItem(UUID agentID, UUID itemID) { InventoryItemBase item = base.GetItem(agentID, itemID); @@ -248,5 +315,84 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return item; } + + #endregion + + #region Inventory manipulation upon arriving/leaving + + // + // These 2 are for local and foreign users coming back, respectively + // + + private void ProcessInventoryForComingHome(IClientAPI client) + { + m_log.DebugFormat("[HG INVENTORY ACCESS MODULE]: Restoring root folder for local user {0}", client.Name); + if (client is IClientCore) + { + IClientCore core = (IClientCore)client; + IClientInventory inv; + + if (core.TryGet(out inv)) + { + InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId); + InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID); + + inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); + } + } + } + + private void ProcessInventoryForArriving(IClientAPI client) + { + } + + // + // These 2 are for local and foreign users going away respectively + // + + private void ProcessInventoryForHypergriding(IClientAPI client) + { + if (client is IClientCore) + { + IClientCore core = (IClientCore)client; + IClientInventory inv; + + if (core.TryGet(out inv)) + { + InventoryFolderBase root = m_Scene.InventoryService.GetRootFolder(client.AgentId); + if (root != null) + { + m_log.DebugFormat("[HG INVENTORY ACCESS MODULE]: Changing root inventory for user {0}", client.Name); + InventoryCollection content = m_Scene.InventoryService.GetFolderContent(client.AgentId, root.ID); + List fids = new List(); + List iids = new List(); + List keep = new List(); + + foreach (InventoryFolderBase f in content.Folders) + { + 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) + it.Name = it.Name + " (Unavailable)"; ; + + // Send the new names + inv.SendBulkUpdateInventory(keep.ToArray(), content.Items.ToArray()); + + } + } + } + } + + private void ProcessInventoryForLeaving(IClientAPI client) + { + } + + #endregion } } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index fe3438e175..b3debb0296 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -502,6 +502,12 @@ namespace OpenSim.Region.Framework.Scenes public delegate void PrimsLoaded(Scene s); public event PrimsLoaded OnPrimsLoaded; + public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout); + public event TeleportStart OnTeleportStart; + + public delegate void TeleportFail(IClientAPI client, bool gridLogout); + public event TeleportFail OnTeleportFail; + public class MoneyTransferArgs : EventArgs { public UUID sender; @@ -2463,5 +2469,48 @@ namespace OpenSim.Region.Framework.Scenes } } } + + public void TriggerTeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout) + { + TeleportStart handler = OnTeleportStart; + + if (handler != null) + { + foreach (TeleportStart d in handler.GetInvocationList()) + { + try + { + d(client, destination, finalDestination, teleportFlags, gridLogout); + } + catch (Exception e) + { + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for TeleportStart failed - continuing {0} - {1}", + e.Message, e.StackTrace); + } + } + } + } + + public void TriggerTeleportFail(IClientAPI client, bool gridLogout) + { + TeleportFail handler = OnTeleportFail; + + if (handler != null) + { + foreach (TeleportFail d in handler.GetInvocationList()) + { + try + { + d(client, gridLogout); + } + catch (Exception e) + { + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for TeleportFail failed - continuing {0} - {1}", + e.Message, e.StackTrace); + } + } + } + } + } }