From a1de9bc33f4f776f91e965af8bcf1a6bbc5deb41 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 29 Mar 2012 01:08:37 +0100 Subject: [PATCH 01/21] Revert "Add comment about setting client.SceneAgent in AddNewClient()" This reverts commit 964cae4f37120db34d0d3e2f08ab998215237dfd. --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 44cd30a70b..60fe48fe64 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2670,10 +2670,7 @@ namespace OpenSim.Region.Framework.Scenes sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); } - // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the - // client is for a root or child agent. client.SceneAgent = sp; - m_LastLogin = Util.EnvironmentTickCount(); // Cache the user's name From 93ac47f0d3968650bd7758ad0981e8e5d49b8138 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 29 Mar 2012 01:08:47 +0100 Subject: [PATCH 02/21] Revert "Simplify friends caching by only doing this for root agents - no functions require caching for child agents." We need to cache child agents so that friends object edit/delete permissions will work across boarders on regions hosted by different simulators. This reverts commit d9f7b8549b3cb9699eb8bd54242d31aac0f8241a. --- OpenSim/Framework/IClientAPI.cs | 2 +- .../ClientStack/Linden/UDP/LLClientView.cs | 4 +- .../Avatar/Friends/FriendsModule.cs | 62 +++++++++++++------ .../Avatar/Friends/HGFriendsModule.cs | 6 +- .../Region/Framework/Scenes/EventManager.cs | 3 +- OpenSim/Region/Framework/Scenes/Scene.cs | 1 - .../Server/IRCClientView.cs | 4 +- .../OptionalModules/World/NPC/NPCAvatar.cs | 2 +- OpenSim/Tests/Common/Mock/TestClient.cs | 2 +- 9 files changed, 55 insertions(+), 31 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 1e36b061d0..3f560d0ec4 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -710,7 +710,7 @@ namespace OpenSim.Framework /// The scene agent for this client. This will only be set if the client has an agent in a scene (i.e. if it /// is connected). /// - ISceneAgent SceneAgent { get; set; } + ISceneAgent SceneAgent { get; } UUID SessionId { get; } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 98996693e0..cd81df5e68 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -384,7 +384,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP set { m_startpos = value; } } public UUID AgentId { get { return m_agentId; } } - public ISceneAgent SceneAgent { get; set; } + public ISceneAgent SceneAgent { get; private set; } public UUID ActiveGroupId { get { return m_activeGroupID; } } public string ActiveGroupName { get { return m_activeGroupName; } } public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } @@ -695,7 +695,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - m_scene.AddNewClient(this, PresenceType.User); + SceneAgent = m_scene.AddNewClient(this, PresenceType.User); RefreshGroupMembership(); } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 4cc0e1972b..aadd3bc16b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { public UUID PrincipalID; public FriendInfo[] Friends; + public int Refcount; public bool IsFriend(string friend) { @@ -254,9 +255,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnNewClient(IClientAPI client) { - if (client.SceneAgent.IsChildAgent) - return; - client.OnInstantMessage += OnInstantMessage; client.OnApproveFriendRequest += OnApproveFriendRequest; client.OnDenyFriendRequest += OnDenyFriendRequest; @@ -283,14 +281,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends UUID agentID = client.AgentId; lock (m_Friends) { - UserFriendData friendsData = new UserFriendData(); - friendsData.PrincipalID = agentID; - friendsData.Friends = GetFriendsFromService(client); + UserFriendData friendsData; + if (m_Friends.TryGetValue(agentID, out friendsData)) + { + friendsData.Refcount++; + return false; + } + else + { + friendsData = new UserFriendData(); + friendsData.PrincipalID = agentID; + friendsData.Friends = GetFriendsFromService(client); + friendsData.Refcount = 1; - m_Friends[agentID] = friendsData; + m_Friends[agentID] = friendsData; + return true; + } } - - return true; } private void OnClientClosed(UUID agentID, Scene scene) @@ -300,17 +307,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { // do this for root agents closing out StatusChange(agentID, false); + } - lock (m_Friends) - m_Friends.Remove(agentID); + lock (m_Friends) + { + UserFriendData friendsData; + if (m_Friends.TryGetValue(agentID, out friendsData)) + { + friendsData.Refcount--; + if (friendsData.Refcount <= 0) + m_Friends.Remove(agentID); + } } } private void OnMakeRootAgent(ScenePresence sp) { - // FIXME: Ideally, we want to avoid doing this here since it sits the EventManager.OnMakeRootAgent event - // is on the critical path for transferring an avatar from one region to another. - CacheFriends(sp.ControllingClient); + RecacheFriends(sp.ControllingClient); } private void OnClientLogin(IClientAPI client) @@ -616,7 +629,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } // Update the local cache. - CacheFriends(client); + RecacheFriends(client); // // Notify the friend @@ -678,7 +691,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.SendAlertMessage("Unable to terminate friendship on this sim."); // Update local cache - CacheFriends(client); + RecacheFriends(client); client.SendTerminateFriend(exfriendID); @@ -799,7 +812,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Update the local cache - CacheFriends(friendClient); + RecacheFriends(friendClient); // we're done return true; @@ -832,7 +845,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // the friend in this sim as root agent friendClient.SendTerminateFriend(exfriendID); // update local cache - CacheFriends(friendClient); + RecacheFriends(friendClient); // we're done return true; } @@ -933,6 +946,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return FriendsService.GetFriends(client.AgentId); } + protected void RecacheFriends(IClientAPI client) + { + // FIXME: Ideally, we want to avoid doing this here since it sits the EventManager.OnMakeRootAgent event + // is on the critical path for transferring an avatar from one region to another. + UUID agentID = client.AgentId; + lock (m_Friends) + { + UserFriendData friendsData; + if (m_Friends.TryGetValue(agentID, out friendsData)) + friendsData.Friends = GetFriendsFromService(client); + } + } + /// /// Are friends cached on this simulator for a particular user? /// diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index 7bc30181a0..e50a84a76e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -121,7 +121,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { UUID agentID = client.AgentId; // we do this only for the root agent - if (!client.SceneAgent.IsChildAgent) + if (m_Friends[agentID].Refcount == 1) { // We need to preload the user management cache with the names // of foreign friends, just like we do with SOPs' creators @@ -426,14 +426,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode); agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString(); - CacheFriends(agentClient); + RecacheFriends(agentClient); } if (friendClient != null) { friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode); friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit); friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString(); - CacheFriends(friendClient); + RecacheFriends(friendClient); } m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}", diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index fe3438e175..7993abed72 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -71,7 +71,6 @@ namespace OpenSim.Region.Framework.Scenes /// Triggered when a new client is added to the scene. /// /// - /// This is triggered for both child and root agent client connections. /// Triggered before OnClientLogin. /// public event OnNewClientDelegate OnNewClient; @@ -192,7 +191,7 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ClientClosed(UUID clientID, Scene scene); /// - /// Fired when a client is removed from a scene whether it's a child or a root agent. + /// Fired when a client is removed from a scene. /// /// /// At the point of firing, the scene still contains the client's scene presence. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 60fe48fe64..c887b4ed09 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2670,7 +2670,6 @@ namespace OpenSim.Region.Framework.Scenes sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); } - client.SceneAgent = sp; m_LastLogin = Util.EnvironmentTickCount(); // Cache the user's name diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 43548e673f..5cf478ac10 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -55,7 +55,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server private UUID m_agentID = UUID.Random(); - public ISceneAgent SceneAgent { get; set; } + public ISceneAgent SceneAgent { get; private set; } private string m_username; private string m_nick; @@ -895,7 +895,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public void Start() { - m_scene.AddNewClient(this, PresenceType.User); + SceneAgent = m_scene.AddNewClient(this, PresenceType.User); // Mimicking LLClientView which gets always set appearance from client. AvatarAppearance appearance; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 5ea5af74a2..16ec34f62c 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -72,7 +72,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC get { return m_ownerID; } } - public ISceneAgent SceneAgent { get; set; } + public ISceneAgent SceneAgent { get { throw new NotImplementedException(); } } public void Say(string message) { diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index d6e72005b5..455b51e595 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -327,7 +327,7 @@ namespace OpenSim.Tests.Common.Mock /// private UUID m_agentId; - public ISceneAgent SceneAgent { get; set; } + public ISceneAgent SceneAgent { get { throw new NotImplementedException(); } } /// /// The last caps seed url that this client was given. From bd83676d6c01b59c5d2b55f81e5f3ce9885f450e Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 29 Mar 2012 01:13:08 +0100 Subject: [PATCH 03/21] Change namespace on CallingCardModule and correct interface file placemant. Also ass OpenSource header --- .../Avatar/Friends/CallingCardModule.cs | 31 +++++++++++++++++-- .../Interfaces}/ICallingCardModule.cs | 0 2 files changed, 29 insertions(+), 2 deletions(-) rename OpenSim/{Framework => Region/Framework/Interfaces}/ICallingCardModule.cs (100%) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs index 5e2a651715..d942e8742a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs @@ -1,4 +1,31 @@ -using System; +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; using System.Collections.Generic; using System.Reflection; using log4net; @@ -10,7 +37,7 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; using Mono.Addins; -namespace Careminster.XCallingCard.Modules +namespace OpenSim.Region.CoreModules.Avatar.Friends { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XCallingCard")] public class CallingCardModule : ISharedRegionModule, ICallingCardModule diff --git a/OpenSim/Framework/ICallingCardModule.cs b/OpenSim/Region/Framework/Interfaces/ICallingCardModule.cs similarity index 100% rename from OpenSim/Framework/ICallingCardModule.cs rename to OpenSim/Region/Framework/Interfaces/ICallingCardModule.cs From 62b1c807c2f1450cb29a7ba44b7e8c01c46383b3 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 29 Mar 2012 01:14:50 +0100 Subject: [PATCH 04/21] Also add OSS header to interface --- .../Interfaces/ICallingCardModule.cs | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Interfaces/ICallingCardModule.cs b/OpenSim/Region/Framework/Interfaces/ICallingCardModule.cs index 17e6de35b6..69682aca0d 100644 --- a/OpenSim/Region/Framework/Interfaces/ICallingCardModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ICallingCardModule.cs @@ -1,4 +1,31 @@ -using System; +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; using System.Collections.Generic; using System.Text; using OpenMetaverse; From 22a85b947a16074525343a56203211806ce16834 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 29 Mar 2012 01:26:30 +0100 Subject: [PATCH 05/21] Add back parts of reverted changes that were not concerned with child agent caching. This adds ScenePresence to IClientAPI.SceneAgent earlier on in the add client process so that its information is available to EventManager.OnNewClient() and OnClientLogin() Also add a code comment as to why we're caching friend information for child agents. --- OpenSim/Framework/IClientAPI.cs | 2 +- OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 4 ++-- OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | 3 +++ OpenSim/Region/Framework/Scenes/EventManager.cs | 3 ++- OpenSim/Region/Framework/Scenes/Scene.cs | 4 ++++ .../Agent/InternetRelayClientView/Server/IRCClientView.cs | 4 ++-- OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs | 2 +- OpenSim/Tests/Common/Mock/TestClient.cs | 2 +- 8 files changed, 16 insertions(+), 8 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 3f560d0ec4..1e36b061d0 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -710,7 +710,7 @@ namespace OpenSim.Framework /// The scene agent for this client. This will only be set if the client has an agent in a scene (i.e. if it /// is connected). /// - ISceneAgent SceneAgent { get; } + ISceneAgent SceneAgent { get; set; } UUID SessionId { get; } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index cd81df5e68..98996693e0 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -384,7 +384,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP set { m_startpos = value; } } public UUID AgentId { get { return m_agentId; } } - public ISceneAgent SceneAgent { get; private set; } + public ISceneAgent SceneAgent { get; set; } public UUID ActiveGroupId { get { return m_activeGroupID; } } public string ActiveGroupName { get { return m_activeGroupName; } } public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } @@ -695,7 +695,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - SceneAgent = m_scene.AddNewClient(this, PresenceType.User); + m_scene.AddNewClient(this, PresenceType.User); RefreshGroupMembership(); } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index aadd3bc16b..0c83679055 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -261,6 +261,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.OnTerminateFriendship += (thisClient, agentID, exfriendID) => RemoveFriendship(thisClient, exfriendID); client.OnGrantUserRights += OnGrantUserRights; + // We need to cache information for child agents as well as root agents so that friend edit/move/delete + // permissions will work across borders where both regions are on different simulators. + // // Do not do this asynchronously. If we do, then subsequent code can outrace CacheFriends() and // return misleading results from the still empty friends cache. // If we absolutely need to do this asynchronously, then a signalling mechanism is needed so that calls diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 7993abed72..fe3438e175 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -71,6 +71,7 @@ namespace OpenSim.Region.Framework.Scenes /// Triggered when a new client is added to the scene. /// /// + /// This is triggered for both child and root agent client connections. /// Triggered before OnClientLogin. /// public event OnNewClientDelegate OnNewClient; @@ -191,7 +192,7 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ClientClosed(UUID clientID, Scene scene); /// - /// Fired when a client is removed from a scene. + /// Fired when a client is removed from a scene whether it's a child or a root agent. /// /// /// At the point of firing, the scene still contains the client's scene presence. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index c887b4ed09..44cd30a70b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2670,6 +2670,10 @@ namespace OpenSim.Region.Framework.Scenes sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); } + // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the + // client is for a root or child agent. + client.SceneAgent = sp; + m_LastLogin = Util.EnvironmentTickCount(); // Cache the user's name diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 5cf478ac10..43548e673f 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -55,7 +55,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server private UUID m_agentID = UUID.Random(); - public ISceneAgent SceneAgent { get; private set; } + public ISceneAgent SceneAgent { get; set; } private string m_username; private string m_nick; @@ -895,7 +895,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public void Start() { - SceneAgent = m_scene.AddNewClient(this, PresenceType.User); + m_scene.AddNewClient(this, PresenceType.User); // Mimicking LLClientView which gets always set appearance from client. AvatarAppearance appearance; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 16ec34f62c..5ea5af74a2 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -72,7 +72,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC get { return m_ownerID; } } - public ISceneAgent SceneAgent { get { throw new NotImplementedException(); } } + public ISceneAgent SceneAgent { get; set; } public void Say(string message) { diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 455b51e595..d6e72005b5 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -327,7 +327,7 @@ namespace OpenSim.Tests.Common.Mock /// private UUID m_agentId; - public ISceneAgent SceneAgent { get { throw new NotImplementedException(); } } + public ISceneAgent SceneAgent { get; set; } /// /// The last caps seed url that this client was given. From 012b01f224dac8259eb0978aa7ef5a098924b7c8 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 29 Mar 2012 03:19:45 +0100 Subject: [PATCH 06/21] Add simple regression test for logging in with offline friends. Don't expect to receive any in this instance. --- .../Avatar/Friends/Tests/FriendModuleTests.cs | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs index 682fbab142..34c68cced5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs @@ -44,6 +44,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests private FriendsModule m_fm; private TestScene m_scene; + [TestFixtureSetUp] + public void FixtureInit() + { + // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. + Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; + } + + [TestFixtureTearDown] + public void TearDown() + { + // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple + // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression + // tests really shouldn't). + Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; + } + [SetUp] public void Init() { @@ -62,7 +78,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests } [Test] - public void TestNoFriends() + public void TestLoginWithNoFriends() { TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); @@ -75,6 +91,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests Assert.That(((TestClient)sp.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(0)); } + [Test] + public void TestLoginWithOfflineFriends() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UUID user1Id = TestHelpers.ParseTail(0x1); + UUID user2Id = TestHelpers.ParseTail(0x2); + +// UserAccountHelpers.CreateUserWithInventory(m_scene, user1Id); +// UserAccountHelpers.CreateUserWithInventory(m_scene, user2Id); +// +// m_fm.AddFriendship(user1Id, user2Id); + + ScenePresence sp1 = SceneHelpers.AddScenePresence(m_scene, user1Id); + ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, user2Id); + + m_fm.AddFriendship(sp1.ControllingClient, user2Id); + + m_scene.RemoveClient(sp1.UUID, true); + m_scene.RemoveClient(sp2.UUID, true); + + ScenePresence sp1Redux = SceneHelpers.AddScenePresence(m_scene, user1Id); + + // We don't expect to receive notifications of offline friends on login, just online. + Assert.That(((TestClient)sp1Redux.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0)); + Assert.That(((TestClient)sp1Redux.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(0)); + } + [Test] public void TestAddFriendshipWhileOnline() { From bf09d6a22be5f8e7a2584eaa11ccbc1c61cc6753 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 29 Mar 2012 18:31:57 +0100 Subject: [PATCH 07/21] refactor: Stop passing both IClientAPI and agentID to friend event listeners, these are redundant. Replace a few magic numbers with FriendRights enum already used elsewhere. --- OpenSim/Framework/IClientAPI.cs | 6 +-- .../ClientStack/Linden/UDP/LLClientView.cs | 13 +++--- .../Avatar/Friends/FriendsModule.cs | 40 ++++++++++--------- .../Avatar/Friends/HGFriendsModule.cs | 4 +- .../Avatar/Friends/Tests/FriendModuleTests.cs | 28 +++++++++++++ .../Services/Interfaces/IFriendsService.cs | 2 +- 6 files changed, 62 insertions(+), 31 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 1e36b061d0..869b069f90 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -296,9 +296,9 @@ namespace OpenSim.Framework public delegate void ConfirmXfer(IClientAPI remoteClient, ulong xferID, uint packetID); public delegate void FriendActionDelegate( - IClientAPI remoteClient, UUID agentID, UUID transactionID, List callingCardFolders); + IClientAPI remoteClient, UUID transactionID, List callingCardFolders); - public delegate void FriendshipTermination(IClientAPI remoteClient, UUID agentID, UUID ExID); + public delegate void FriendshipTermination(IClientAPI remoteClient, UUID ExID); public delegate void MoneyTransferRequest( UUID sourceID, UUID destID, int amount, int transactionType, string description); @@ -458,7 +458,7 @@ namespace OpenSim.Framework public delegate void AvatarNotesUpdate(IClientAPI client, UUID targetID, string notes); public delegate void MuteListRequest(IClientAPI client, uint muteCRC); public delegate void AvatarInterestUpdate(IClientAPI client, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages); - public delegate void GrantUserFriendRights(IClientAPI client, UUID requester, UUID target, int rights); + public delegate void GrantUserFriendRights(IClientAPI client, UUID target, int rights); public delegate void PlacesQuery(UUID QueryID, UUID TransactionID, string QueryText, uint QueryFlags, byte Category, string SimName, IClientAPI client); public delegate void AgentFOV(IClientAPI client, float verticalAngle); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 98996693e0..f79597ea3d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -5784,7 +5784,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // My guess is this is the folder to stick the calling card into List callingCardFolders = new List(); - UUID agentID = afriendpack.AgentData.AgentID; UUID transactionID = afriendpack.TransactionBlock.TransactionID; for (int fi = 0; fi < afriendpack.FolderData.Length; fi++) @@ -5795,10 +5794,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP FriendActionDelegate handlerApproveFriendRequest = OnApproveFriendRequest; if (handlerApproveFriendRequest != null) { - handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders); + handlerApproveFriendRequest(this, transactionID, callingCardFolders); } - return true; + return true; } private bool HandlerDeclineFriendship(IClientAPI sender, Packet Pack) @@ -5817,7 +5816,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (OnDenyFriendRequest != null) { OnDenyFriendRequest(this, - dfriendpack.AgentData.AgentID, dfriendpack.TransactionBlock.TransactionID, null); } @@ -5837,14 +5835,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion - UUID listOwnerAgentID = tfriendpack.AgentData.AgentID; UUID exFriendID = tfriendpack.ExBlock.OtherID; FriendshipTermination TerminateFriendshipHandler = OnTerminateFriendship; if (TerminateFriendshipHandler != null) { - TerminateFriendshipHandler(this, listOwnerAgentID, exFriendID); + TerminateFriendshipHandler(this, exFriendID); return true; } + return false; } @@ -11162,12 +11160,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } #endregion + GrantUserFriendRights GrantUserRightsHandler = OnGrantUserRights; if (GrantUserRightsHandler != null) GrantUserRightsHandler(this, - GrantUserRights.AgentData.AgentID, GrantUserRights.Rights[0].AgentRelated, GrantUserRights.Rights[0].RelatedRights); + return true; } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 0c83679055..86e04b9213 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -258,7 +258,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.OnInstantMessage += OnInstantMessage; client.OnApproveFriendRequest += OnApproveFriendRequest; client.OnDenyFriendRequest += OnDenyFriendRequest; - client.OnTerminateFriendship += (thisClient, agentID, exfriendID) => RemoveFriendship(thisClient, exfriendID); + client.OnTerminateFriendship += RemoveFriendship; client.OnGrantUserRights += OnGrantUserRights; // We need to cache information for child agents as well as root agents so that friend edit/move/delete @@ -355,14 +355,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Send the friends online List online = GetOnlineFriends(agentID); - if (online.Count > 0) - { - m_log.DebugFormat( - "[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", - client.Name, client.Scene.RegionInfo.RegionName, online.Count); +// m_log.DebugFormat( +// "[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", +// client.Name, client.Scene.RegionInfo.RegionName, online.Count); + + if (online.Count > 0) client.SendAgentOnline(online.ToArray()); - } // Send outstanding friendship offers List outstanding = new List(); @@ -495,7 +494,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends List friendList = new List(); foreach (FriendInfo fi in friends) { - if (((fi.MyFlags & 1) != 0) && (fi.TheirFlags != -1)) + if (((fi.MyFlags & (int)FriendRights.CanSeeOnline) != 0) && (fi.TheirFlags != -1)) friendList.Add(fi); } @@ -614,7 +613,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; } - protected virtual void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) + protected virtual void OnApproveFriendRequest(IClientAPI client, UUID friendID, List callingCardFolders) { m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", client.AgentId, friendID); @@ -659,18 +658,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) + private void OnDenyFriendRequest(IClientAPI client, UUID friendID, List callingCardFolders) { - m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID); + m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", client.AgentId, friendID); - DeleteFriendship(agentID, friendID); + DeleteFriendship(client.AgentId, friendID); // // Notify the friend // // Try local - if (LocalFriendshipDenied(agentID, client.Name, friendID)) + if (LocalFriendshipDenied(client.AgentId, client.Name, friendID)) return; PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); @@ -681,7 +680,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); if (region != null) - m_FriendsSimConnector.FriendshipDenied(region, agentID, client.Name, friendID); + m_FriendsSimConnector.FriendshipDenied(region, client.AgentId, client.Name, friendID); else m_log.WarnFormat("[FRIENDS]: Could not find region {0} in locating {1}", friendSession.RegionID, friendID); } @@ -718,11 +717,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) + private void OnGrantUserRights(IClientAPI remoteClient, UUID target, int rights) { - m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); + UUID requester = remoteClient.AgentId; - FriendInfo[] friends = GetFriends(remoteClient.AgentId); + m_log.DebugFormat( + "[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", + requester, rights, target); + + FriendInfo[] friends = GetFriends(requester); if (friends.Length == 0) { return; @@ -769,7 +772,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } else + { m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester); + } } protected virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) @@ -813,7 +818,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends ccm.CreateCallingCard(friendID, userID, UUID.Zero); } - // Update the local cache RecacheFriends(friendClient); diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index e50a84a76e..b666daed56 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -105,12 +105,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion - protected override void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) + protected override void OnApproveFriendRequest(IClientAPI client, UUID friendID, List callingCardFolders) { // Update the local cache. Yes, we need to do it right here // because the HGFriendsService placed something on the DB // from under the sim - base.OnApproveFriendRequest(client, agentID, friendID, callingCardFolders); + base.OnApproveFriendRequest(client, friendID, callingCardFolders); } protected override bool CacheFriends(IClientAPI client) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs index 34c68cced5..94a78cbd25 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs @@ -120,6 +120,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests Assert.That(((TestClient)sp1Redux.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(0)); } +// [Test] +// public void TestLoginWithOnlineFriends() +// { +// TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); +// +// UUID user1Id = TestHelpers.ParseTail(0x1); +// UUID user2Id = TestHelpers.ParseTail(0x2); +// +//// UserAccountHelpers.CreateUserWithInventory(m_scene, user1Id); +//// UserAccountHelpers.CreateUserWithInventory(m_scene, user2Id); +//// +//// m_fm.AddFriendship(user1Id, user2Id); +// +// ScenePresence sp1 = SceneHelpers.AddScenePresence(m_scene, user1Id); +// SceneHelpers.AddScenePresence(m_scene, user2Id); +// +// m_fm.AddFriendship(sp1.ControllingClient, user2Id); +//// m_fm.LocalGrantRights +// +// m_scene.RemoveClient(sp1.UUID, true); +// +// ScenePresence sp1Redux = SceneHelpers.AddScenePresence(m_scene, user1Id); +// +// Assert.That(((TestClient)sp1Redux.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0)); +// Assert.That(((TestClient)sp1Redux.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(1)); +// } + [Test] public void TestAddFriendshipWhileOnline() { diff --git a/OpenSim/Services/Interfaces/IFriendsService.cs b/OpenSim/Services/Interfaces/IFriendsService.cs index 1664f3b3e1..fe94242d90 100644 --- a/OpenSim/Services/Interfaces/IFriendsService.cs +++ b/OpenSim/Services/Interfaces/IFriendsService.cs @@ -51,7 +51,7 @@ namespace OpenSim.Services.Interfaces Friend = string.Empty; if (kvp.ContainsKey("Friend") && kvp["Friend"] != null) Friend = kvp["Friend"].ToString(); - MyFlags = 0; + MyFlags = (int)FriendRights.None; if (kvp.ContainsKey("MyFlags") && kvp["MyFlags"] != null) Int32.TryParse(kvp["MyFlags"].ToString(), out MyFlags); TheirFlags = 0; From 30db0ac5e2204c8299355ddf7ddb301966afb3b5 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 29 Mar 2012 16:25:55 -0700 Subject: [PATCH 08/21] Finish up the SuitcaseInventory service. --- .../HGSuitcaseInventoryService.cs | 328 ++++++++++++------ 1 file changed, 213 insertions(+), 115 deletions(-) diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs index a9998866d2..cb686e26e6 100644 --- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Linq; using OpenMetaverse; using log4net; using Nini.Config; @@ -58,6 +59,8 @@ namespace OpenSim.Services.HypergridService private UserAccountCache m_Cache; + private ExpiringCache> m_SuitcaseTrees = new ExpiringCache>(); + public HGSuitcaseInventoryService(IConfigSource config, string configName) : base(config, configName) { @@ -147,16 +150,17 @@ namespace OpenSim.Services.HypergridService return GetRootFolder(principalID); } - // - // Use the inherited methods - // 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 { - XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); if (suitcase != null) { coll = base.GetFolderContent(principalID, suitcase.folderID); @@ -180,68 +184,69 @@ namespace OpenSim.Services.HypergridService return coll; } - //public List GetFolderItems(UUID principalID, UUID folderID) - //{ - //} - - //public override bool AddFolder(InventoryFolderBase folder) - //{ - // // Check if it's under the Suitcase folder - // List skel = base.GetInventorySkeleton(folder.Owner); - // InventoryFolderBase suitcase = GetRootFolder(folder.Owner); - // List suitDescendents = GetDescendents(skel, suitcase.ID); - - // foreach (InventoryFolderBase f in suitDescendents) - // if (folder.ParentID == f.ID) - // { - // XInventoryFolder xFolder = ConvertFromOpenSim(folder); - // return m_Database.StoreFolder(xFolder); - // } - // return false; - //} - - private List GetDescendents(List lst, UUID root) + public override List GetFolderItems(UUID principalID, UUID folderID) { - List direct = lst.FindAll(delegate(InventoryFolderBase f) { return f.ParentID == root; }); - if (direct == null) - return new List(); + // 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); - List indirect = new List(); - foreach (InventoryFolderBase f in direct) - indirect.AddRange(GetDescendents(lst, f.ID)); + if (!IsWithinSuitcaseTree(folderID, root, suitcase)) + return new List(); - direct.AddRange(indirect); - return direct; + return base.GetFolderItems(principalID, folderID); } - // Use inherited method - //public bool UpdateFolder(InventoryFolderBase folder) - //{ - //} + public override bool AddFolder(InventoryFolderBase folder) + { + // 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); - //public override bool MoveFolder(InventoryFolderBase folder) - //{ - // XInventoryFolder[] x = m_Database.GetFolders( - // new string[] { "folderID" }, - // new string[] { folder.ID.ToString() }); + if (!IsWithinSuitcaseTree(folder.ParentID, root, suitcase)) + return false; - // if (x.Length == 0) - // 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; + } - // // Check if it's under the Suitcase folder - // List skel = base.GetInventorySkeleton(folder.Owner); - // InventoryFolderBase suitcase = GetRootFolder(folder.Owner); - // List suitDescendents = GetDescendents(skel, suitcase.ID); + return base.AddFolder(folder); + } - // foreach (InventoryFolderBase f in suitDescendents) - // if (folder.ParentID == f.ID) - // { - // x[0].parentFolderID = folder.ParentID; - // return m_Database.StoreFolder(x[0]); - // } + public bool UpdateFolder(InventoryFolderBase folder) + { + XInventoryFolder root = GetRootXFolder(folder.Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); - // return false; - //} + if (!IsWithinSuitcaseTree(folder.ID, root, suitcase)) + return false; + + 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) { @@ -255,78 +260,110 @@ namespace OpenSim.Services.HypergridService return false; } - // Unfortunately we need to use the inherited method because of how DeRez works. - // The viewer sends the folderID hard-wired in the derez message - //public override bool AddItem(InventoryItemBase item) - //{ - // // Check if it's under the Suitcase folder - // List skel = base.GetInventorySkeleton(item.Owner); - // InventoryFolderBase suitcase = GetRootFolder(item.Owner); - // List suitDescendents = GetDescendents(skel, suitcase.ID); + 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); - // foreach (InventoryFolderBase f in suitDescendents) - // if (item.Folder == f.ID) - // return m_Database.StoreItem(ConvertFromOpenSim(item)); + if (!IsWithinSuitcaseTree(item.Folder, root, suitcase)) + return false; - // 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; + } - //public override bool UpdateItem(InventoryItemBase item) - //{ - // // Check if it's under the Suitcase folder - // List skel = base.GetInventorySkeleton(item.Owner); - // InventoryFolderBase suitcase = GetRootFolder(item.Owner); - // List suitDescendents = GetDescendents(skel, suitcase.ID); + return base.AddItem(item); - // foreach (InventoryFolderBase f in suitDescendents) - // if (item.Folder == f.ID) - // return m_Database.StoreItem(ConvertFromOpenSim(item)); + } - // return false; - //} + public override bool UpdateItem(InventoryItemBase item) + { + XInventoryFolder root = GetRootXFolder(item.Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); - //public override bool MoveItems(UUID principalID, List items) - //{ - // // Principal is b0rked. *sigh* - // // - // // Let's assume they all have the same principal - // // Check if it's under the Suitcase folder - // List skel = base.GetInventorySkeleton(items[0].Owner); - // InventoryFolderBase suitcase = GetRootFolder(items[0].Owner); - // List suitDescendents = GetDescendents(skel, suitcase.ID); + if (!IsWithinSuitcaseTree(item.Folder, root, suitcase)) + return false; - // foreach (InventoryItemBase i in items) - // { - // foreach (InventoryFolderBase f in suitDescendents) - // if (i.Folder == f.ID) - // m_Database.MoveItem(i.ID.ToString(), i.Folder.ToString()); - // } + return base.UpdateItem(item); + } - // return true; - //} + public override bool MoveItems(UUID principalID, List items) + { + // Principal is b0rked. *sigh* + + 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) + { + // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveItem to root folder for user {0}. Moving it to suitcase instead", it.Owner); + it.Folder = suitcase.folderID; + } + + return base.MoveItems(principalID, items); + + } // Let these pass. Use inherited methods. - //public bool DeleteItems(UUID principalID, List itemIDs) - //{ - //} + public override bool DeleteItems(UUID principalID, List itemIDs) + { + return false; + } - //public override InventoryItemBase GetItem(InventoryItemBase item) - //{ - // InventoryItemBase it = base.GetItem(item); - // if (it != null) - // { - // UserAccount user = m_Cache.GetUser(it.CreatorId); + public override InventoryItemBase GetItem(InventoryItemBase item) + { + InventoryItemBase it = base.GetItem(item); + XInventoryFolder root = GetRootXFolder(it.Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner); - // // 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; - //} + if (it != null) + { + if (!IsWithinSuitcaseTree(it.Folder, root, suitcase)) + return null; - //public InventoryFolderBase GetFolder(InventoryFolderBase folder) - //{ - //} + 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; + //} + } + + return it; + } + + public override 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; + + if (f.ParentID == suitcase.folderID) + f.ParentID = root.folderID; + } + + return f; + } //public List GetActiveGestures(UUID principalID) //{ @@ -336,6 +373,19 @@ namespace OpenSim.Services.HypergridService //{ //} + #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( @@ -364,5 +414,53 @@ namespace OpenSim.Services.HypergridService suitcase.folderID = rootID; suitcase.parentFolderID = UUID.Zero; } + + private List GetFolderTree(UUID root) + { + List t = null; + if (m_SuitcaseTrees.TryGetValue(root, out t)) + return t; + + t = GetFolderTreeRecursive(root); + m_SuitcaseTrees.AddOrUpdate(root, 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; + } + + } + + 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 } } From 59157d9d63c0e038ca0a619bfae1be3ed6f77677 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 30 Mar 2012 00:40:19 +0100 Subject: [PATCH 09/21] Add simple login test with online friends. Add IFriendsModule.GrantRights() for granting rights via a module call. Rename IFriendsModule.GetFriendPerms() -> GetRightsGrantedByFriend() to be more self-documenting and consistent with friends module terminology. Add some method doc. --- OpenSim/Data/Null/NullFriendsData.cs | 31 +++++++- OpenSim/Data/Null/NullPresenceData.cs | 1 - .../Avatar/Friends/FriendsModule.cs | 50 +++++++------ .../Avatar/Friends/Tests/FriendModuleTests.cs | 73 ++++++++++++------- .../Presence/PresenceDetector.cs | 9 +-- .../World/Permissions/PermissionsModule.cs | 10 +-- .../Framework/Interfaces/IFriendsModule.cs | 24 +++++- .../Services/Interfaces/IFriendsService.cs | 8 ++ .../PresenceService/PresenceService.cs | 7 +- OpenSim/Tests/Common/Helpers/SceneHelpers.cs | 12 ++- OpenSim/Tests/Common/Mock/TestClient.cs | 36 +++++---- prebuild.xml | 1 + 12 files changed, 177 insertions(+), 85 deletions(-) diff --git a/OpenSim/Data/Null/NullFriendsData.cs b/OpenSim/Data/Null/NullFriendsData.cs index 0a4b2426a8..0be32a4ede 100644 --- a/OpenSim/Data/Null/NullFriendsData.cs +++ b/OpenSim/Data/Null/NullFriendsData.cs @@ -28,6 +28,8 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Reflection; +using log4net; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Data; @@ -36,12 +38,25 @@ namespace OpenSim.Data.Null { public class NullFriendsData : IFriendsData { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static List m_Data = new List(); public NullFriendsData(string connectionString, string realm) { } + /// + /// Clear all friends data + /// + /// + /// This is required by unit tests to clear the static data between test runs. + /// + public static void Clear() + { + m_Data.Clear(); + } + public FriendsData[] GetFriends(UUID principalID) { return GetFriends(principalID.ToString()); @@ -66,9 +81,16 @@ namespace OpenSim.Data.Null lst.ForEach(f => { FriendsData f2 = m_Data.Find(candidateF2 => f.Friend == candidateF2.PrincipalID); - if (f2 != null) { f.Data["TheirFlags"] = f2.Data["Flags"]; } + if (f2 != null) + f.Data["TheirFlags"] = f2.Data["Flags"]; + +// m_log.DebugFormat( +// "[NULL FRIENDS DATA]: Got {0} {1} {2} for {3}", +// f.Friend, f.Data["Flags"], f2 != null ? f.Data["TheirFlags"] : "not found!", f.PrincipalID); }); +// m_log.DebugFormat("[NULL FRIENDS DATA]: Got {0} friends for {1}", lst.Count, userID); + return lst.ToArray(); } @@ -80,6 +102,9 @@ namespace OpenSim.Data.Null if (data == null) return false; +// m_log.DebugFormat( +// "[NULL FRIENDS DATA]: Storing {0} {1} {2}", data.PrincipalID, data.Friend, data.Data["Flags"]); + m_Data.Add(data); return true; @@ -98,6 +123,10 @@ namespace OpenSim.Data.Null FriendsData friend = lst.Find(delegate(FriendsData fdata) { return fdata.Friend == friendID; }); if (friendID != null) { +// m_log.DebugFormat( +// "[NULL FRIENDS DATA]: Deleting friend {0} {1} for {2}", +// friend.Friend, friend.Data["Flags"], friend.PrincipalID); + m_Data.Remove(friend); return true; } diff --git a/OpenSim/Data/Null/NullPresenceData.cs b/OpenSim/Data/Null/NullPresenceData.cs index 91f1cc561e..c06c223a81 100644 --- a/OpenSim/Data/Null/NullPresenceData.cs +++ b/OpenSim/Data/Null/NullPresenceData.cs @@ -110,7 +110,6 @@ namespace OpenSim.Data.Null return false; } - public PresenceData[] Get(string field, string data) { if (Instance != this) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 86e04b9213..9d7012ec20 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -51,6 +51,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { public class FriendsModule : ISharedRegionModule, IFriendsModule { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + protected bool m_Enabled = false; protected class UserFriendData @@ -72,7 +74,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } protected static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0]; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected List m_Scenes = new List(); @@ -156,7 +157,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends InitModule(config); m_Enabled = true; - m_log.InfoFormat("[FRIENDS MODULE]: {0} enabled.", Name); + m_log.DebugFormat("[FRIENDS MODULE]: {0} enabled.", Name); } } } @@ -201,7 +202,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (!m_Enabled) return; - m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name); +// m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name); m_Scenes.Add(scene); scene.RegisterModuleInterface(this); @@ -241,13 +242,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion - public virtual uint GetFriendPerms(UUID principalID, UUID friendID) + public virtual int GetRightsGrantedByFriend(UUID principalID, UUID friendID) { FriendInfo[] friends = GetFriends(principalID); FriendInfo finfo = GetFriend(friends, friendID); if (finfo != null) { - return (uint)finfo.TheirFlags; + return finfo.TheirFlags; } return 0; @@ -259,7 +260,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.OnApproveFriendRequest += OnApproveFriendRequest; client.OnDenyFriendRequest += OnDenyFriendRequest; client.OnTerminateFriendship += RemoveFriendship; - client.OnGrantUserRights += OnGrantUserRights; + client.OnGrantUserRights += GrantRights; // We need to cache information for child agents as well as root agents so that friend edit/move/delete // permissions will work across borders where both regions are on different simulators. @@ -356,10 +357,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Send the friends online List online = GetOnlineFriends(agentID); -// m_log.DebugFormat( -// "[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", -// client.Name, client.Scene.RegionInfo.RegionName, online.Count); - if (online.Count > 0) client.SendAgentOnline(online.ToArray()); @@ -421,23 +418,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends List GetOnlineFriends(UUID userID) { List friendList = new List(); - List online = new List(); FriendInfo[] friends = GetFriends(userID); foreach (FriendInfo fi in friends) { - if (((fi.TheirFlags & 1) != 0) && (fi.TheirFlags != -1)) + if (((fi.TheirFlags & (int)FriendRights.CanSeeOnline) != 0) && (fi.TheirFlags != -1)) friendList.Add(fi.Friend); } + List online = new List(); + if (friendList.Count > 0) GetOnlineFriends(userID, friendList, online); +// m_log.DebugFormat( +// "[FRIENDS MODULE]: User {0} has {1} friends online", userID, online.Count); + return online; } protected virtual void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) { +// m_log.DebugFormat( +// "[FRIENDS MODULE]: Looking for online presence of {0} users for {1}", friendList.Count, userID); + PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray()); foreach (PresenceInfo pi in presence) { @@ -717,13 +721,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - private void OnGrantUserRights(IClientAPI remoteClient, UUID target, int rights) + public void GrantRights(IClientAPI remoteClient, UUID friendID, int rights) { UUID requester = remoteClient.AgentId; m_log.DebugFormat( "[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", - requester, rights, target); + requester, rights, friendID); FriendInfo[] friends = GetFriends(requester); if (friends.Length == 0) @@ -732,12 +736,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } // Let's find the friend in this user's friend list - FriendInfo friend = GetFriend(friends, target); + FriendInfo friend = GetFriend(friends, friendID); if (friend != null) // Found it { // Store it on the DB - if (!StoreRights(requester, target, rights)) + if (!StoreRights(requester, friendID, rights)) { remoteClient.SendAlertMessage("Unable to grant rights."); return; @@ -748,17 +752,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends friend.MyFlags = rights; // Always send this back to the original client - remoteClient.SendChangeUserRights(requester, target, rights); + remoteClient.SendChangeUserRights(requester, friendID, rights); // // Notify the friend // // Try local - if (LocalGrantRights(requester, target, myFlags, rights)) + if (LocalGrantRights(requester, friendID, myFlags, rights)) return; - PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { target.ToString() }); + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); if (friendSessions != null && friendSessions.Length > 0) { PresenceInfo friendSession = friendSessions[0]; @@ -767,13 +771,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); // TODO: You might want to send the delta to save the lookup // on the other end!! - m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights); + m_FriendsSimConnector.GrantRights(region, requester, friendID, myFlags, rights); } } } else { - m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester); + m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", friendID, requester); } } @@ -990,8 +994,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends protected virtual void StoreFriendships(UUID agentID, UUID friendID) { - FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), 1); - FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 1); + FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), (int)FriendRights.CanSeeOnline); + FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), (int)FriendRights.CanSeeOnline); } protected virtual bool DeleteFriendship(UUID agentID, UUID exfriendID) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs index 94a78cbd25..45b4264c91 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using Nini.Config; using NUnit.Framework; using OpenMetaverse; +using OpenSim.Data.Null; using OpenSim.Framework; using OpenSim.Region.CoreModules.Avatar.Friends; using OpenSim.Region.Framework.Scenes; @@ -63,6 +64,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests [SetUp] public void Init() { + // We must clear friends data between tests since Data.Null holds it in static properties. This is necessary + // so that different services and simulator can share the data in standalone mode. This is pretty horrible + // effectively the statics are global variables. + NullFriendsData.Clear(); + IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); // Not strictly necessary since FriendsModule assumes it is the default (!) @@ -110,8 +116,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests m_fm.AddFriendship(sp1.ControllingClient, user2Id); - m_scene.RemoveClient(sp1.UUID, true); - m_scene.RemoveClient(sp2.UUID, true); + // Not necessary for this test. CanSeeOnline is automatically granted. +// m_fm.GrantRights(sp1.ControllingClient, user2Id, (int)FriendRights.CanSeeOnline); + + // We must logout from the client end so that the presence service is correctly updated by the presence + // detector. This is listening to the OnConnectionClosed event on the client. + ((TestClient)sp1.ControllingClient).Logout(); + ((TestClient)sp2.ControllingClient).Logout(); +// m_scene.RemoveClient(sp1.UUID, true); +// m_scene.RemoveClient(sp2.UUID, true); ScenePresence sp1Redux = SceneHelpers.AddScenePresence(m_scene, user1Id); @@ -120,33 +133,39 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests Assert.That(((TestClient)sp1Redux.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(0)); } -// [Test] -// public void TestLoginWithOnlineFriends() -// { -// TestHelpers.InMethod(); + [Test] + public void TestLoginWithOnlineFriends() + { + TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); + + UUID user1Id = TestHelpers.ParseTail(0x1); + UUID user2Id = TestHelpers.ParseTail(0x2); + +// UserAccountHelpers.CreateUserWithInventory(m_scene, user1Id); +// UserAccountHelpers.CreateUserWithInventory(m_scene, user2Id); // -// UUID user1Id = TestHelpers.ParseTail(0x1); -// UUID user2Id = TestHelpers.ParseTail(0x2); -// -//// UserAccountHelpers.CreateUserWithInventory(m_scene, user1Id); -//// UserAccountHelpers.CreateUserWithInventory(m_scene, user2Id); -//// -//// m_fm.AddFriendship(user1Id, user2Id); -// -// ScenePresence sp1 = SceneHelpers.AddScenePresence(m_scene, user1Id); -// SceneHelpers.AddScenePresence(m_scene, user2Id); -// -// m_fm.AddFriendship(sp1.ControllingClient, user2Id); -//// m_fm.LocalGrantRights -// -// m_scene.RemoveClient(sp1.UUID, true); -// -// ScenePresence sp1Redux = SceneHelpers.AddScenePresence(m_scene, user1Id); -// -// Assert.That(((TestClient)sp1Redux.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0)); -// Assert.That(((TestClient)sp1Redux.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(1)); -// } +// m_fm.AddFriendship(user1Id, user2Id); + + ScenePresence sp1 = SceneHelpers.AddScenePresence(m_scene, user1Id); + ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, user2Id); + + m_fm.AddFriendship(sp1.ControllingClient, user2Id); + + // Not necessary for this test. CanSeeOnline is automatically granted. +// m_fm.GrantRights(sp1.ControllingClient, user2Id, (int)FriendRights.CanSeeOnline); + + // We must logout from the client end so that the presence service is correctly updated by the presence + // detector. This is listening to the OnConnectionClosed event on the client. +// ((TestClient)sp1.ControllingClient).Logout(); + ((TestClient)sp2.ControllingClient).Logout(); +// m_scene.RemoveClient(user2Id, true); + + ScenePresence sp2Redux = SceneHelpers.AddScenePresence(m_scene, user2Id); + + Assert.That(((TestClient)sp2Redux.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0)); + Assert.That(((TestClient)sp2Redux.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(1)); + } [Test] public void TestAddFriendshipWhileOnline() diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs index e2e383f060..ccfbf78a29 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs @@ -27,14 +27,12 @@ using System; using System.Collections.Generic; using System.Reflection; - +using log4net; +using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; -using OpenMetaverse; -using log4net; - namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence { public class PresenceDetector @@ -97,7 +95,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence // m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); m_PresenceService.LogoutAgent(client.SessionId); } - } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index ac03747620..64759a7e12 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -487,7 +487,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return false; } - protected bool IsFriendWithPerms(UUID user,UUID objectOwner) + protected bool IsFriendWithPerms(UUID user, UUID objectOwner) { if (user == UUID.Zero) return false; @@ -495,11 +495,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (m_friendsModule == null) return false; - uint friendPerms = m_friendsModule.GetFriendPerms(user, objectOwner); - if ((friendPerms & (uint)FriendRights.CanModifyObjects) != 0) - return true; - - return false; + int friendPerms = m_friendsModule.GetRightsGrantedByFriend(user, objectOwner); + return (friendPerms & (int)FriendRights.CanModifyObjects) != 0; } protected bool IsEstateManager(UUID user) @@ -508,6 +505,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return m_scene.RegionInfo.EstateSettings.IsEstateManager(user); } + #endregion public bool PropagatePermissions() diff --git a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs index 061799e394..10bef1e2dc 100644 --- a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs @@ -55,7 +55,27 @@ namespace OpenSim.Region.Framework.Interfaces /// void RemoveFriendship(IClientAPI client, UUID exFriendID); - uint GetFriendPerms(UUID PrincipalID, UUID FriendID); + /// + /// Get permissions granted by a friend. + /// + /// The user. + /// The friend that granted. + /// The permissions. These come from the FriendRights enum. + int GetRightsGrantedByFriend(UUID PrincipalID, UUID FriendID); + + /// + /// Grant permissions for a friend. + /// + /// + /// This includes giving them the ability to see when the user is online and permission to edit the user's + /// objects. + /// Granting lower permissions than the friend currently has will rescind the extra permissions. + /// + /// The user granting the permissions. + /// The friend. + /// These come from the FriendRights enum. + void GrantRights(IClientAPI remoteClient, UUID friendID, int perms); + bool SendFriendsOnlineIfNeeded(IClientAPI client); } -} +} \ No newline at end of file diff --git a/OpenSim/Services/Interfaces/IFriendsService.cs b/OpenSim/Services/Interfaces/IFriendsService.cs index fe94242d90..d0d3b1002d 100644 --- a/OpenSim/Services/Interfaces/IFriendsService.cs +++ b/OpenSim/Services/Interfaces/IFriendsService.cs @@ -36,7 +36,15 @@ namespace OpenSim.Services.Interfaces { public UUID PrincipalID; public string Friend; + + /// + /// The permissions that this user has granted to the friend. + /// public int MyFlags; + + /// + /// The permissions that the friend has granted to this user. + /// public int TheirFlags; public FriendInfo() diff --git a/OpenSim/Services/PresenceService/PresenceService.cs b/OpenSim/Services/PresenceService/PresenceService.cs index c8ac38e63a..ed2703eda5 100644 --- a/OpenSim/Services/PresenceService/PresenceService.cs +++ b/OpenSim/Services/PresenceService/PresenceService.cs @@ -151,11 +151,12 @@ namespace OpenSim.Services.PresenceService info.Add(ret); } + +// m_log.DebugFormat( +// "[PRESENCE SERVICE]: GetAgents for {0} found {1} presences", userIDStr, data.Length); } - // m_log.DebugFormat("[PRESENCE SERVICE]: GetAgents for {0} userIDs found {1} presences", userIDs.Length, info.Count); return info.ToArray(); } - } -} +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs index 7bf08ae702..318758d984 100644 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs @@ -369,8 +369,11 @@ namespace OpenSim.Tests.Common agentData.AgentID = agentId; agentData.firstname = firstName; agentData.lastname = "testlastname"; - agentData.SessionID = UUID.Zero; - agentData.SecureSessionID = UUID.Zero; + + // XXX: Sessions must be unique, otherwise one presence can overwrite another in NullPresenceData. + agentData.SessionID = UUID.Random(); + agentData.SecureSessionID = UUID.Random(); + agentData.circuitcode = 123; agentData.BaseFolder = UUID.Zero; agentData.InventoryFolder = UUID.Zero; @@ -416,7 +419,10 @@ namespace OpenSim.Tests.Common // We emulate the proper login sequence here by doing things in four stages // Stage 0: login - scene.PresenceService.LoginAgent(agentData.AgentID.ToString(), agentData.SessionID, agentData.SecureSessionID); + // We need to punch through to the underlying service because scene will not, correctly, let us call it + // through it's reference to the LPSC + LocalPresenceServicesConnector lpsc = (LocalPresenceServicesConnector)scene.PresenceService; + lpsc.m_PresenceService.LoginAgent(agentData.AgentID.ToString(), agentData.SessionID, agentData.SecureSessionID); // Stages 1 & 2 ScenePresence sp = IntroduceClientToScene(scene, agentData, TeleportFlags.ViaLogin); diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index d6e72005b5..cb9840e4f7 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -347,15 +347,9 @@ namespace OpenSim.Tests.Common.Mock get { return m_agentId; } } - public UUID SessionId - { - get { return UUID.Zero; } - } + public UUID SessionId { get; set; } - public UUID SecureSessionId - { - get { return UUID.Zero; } - } + public UUID SecureSessionId { get; set; } public virtual string FirstName { @@ -379,11 +373,9 @@ namespace OpenSim.Tests.Common.Mock get { return true; } set { } } - public bool IsLoggingOut - { - get { return false; } - set { } - } + + public bool IsLoggingOut { get; set; } + public UUID ActiveGroupId { get { return UUID.Zero; } @@ -449,6 +441,8 @@ namespace OpenSim.Tests.Common.Mock m_lastName = agentData.lastname; m_circuitCode = agentData.circuitcode; m_scene = scene; + SessionId = agentData.SessionID; + SecureSessionId = agentData.SecureSessionID; CapsSeedUrl = agentData.CapsPath; ReceivedOfflineNotifications = new List(); @@ -900,8 +894,24 @@ namespace OpenSim.Tests.Common.Mock { } + /// + /// This is a TestClient only method to do shutdown tasks that are normally carried out by LLUDPServer.RemoveClient() + /// + public void Logout() + { + // We must set this here so that the presence is removed from the PresenceService by the PresenceDetector + IsLoggingOut = true; + + Close(); + } + public void Close() { + // Fire the callback for this connection closing + // This is necesary to get the presence detector to notice that a client has logged out. + if (OnConnectionClosed != null) + OnConnectionClosed(this); + m_scene.RemoveClient(AgentId, true); } diff --git a/prebuild.xml b/prebuild.xml index f8d03f3325..4ceb137b1d 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2913,6 +2913,7 @@ + From bce7964ac2b0e67ff8c8e5ab00bb45b93da219ad Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 30 Mar 2012 01:05:29 +0100 Subject: [PATCH 10/21] refactor: Move "friends show cache" console command out into separate FriendsCommandsModule. Expose required methods on IFriendsModule. Rename GetFriends() -> GetFriendsFromCache() for self-documentation --- .../Avatar/Friends/FriendsModule.cs | 98 ++--------- .../Avatar/Friends/HGFriendsModule.cs | 14 +- .../Framework/Interfaces/IFriendsModule.cs | 25 ++- .../Avatar/Friends/FriendsCommandsModule.cs | 165 ++++++++++++++++++ 4 files changed, 205 insertions(+), 97 deletions(-) create mode 100644 OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 9d7012ec20..37e6600e4d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -213,14 +213,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends scene.EventManager.OnClientLogin += OnClientLogin; } - public virtual void RegionLoaded(Scene scene) - { - scene.AddCommand( - "Friends", this, "friends show cache", - "friends show cache [ ]", - "Show the friends cache for the given user", - HandleFriendsShowCacheCommand); - } + public virtual void RegionLoaded(Scene scene) {} public void RemoveRegion(Scene scene) { @@ -244,7 +237,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends public virtual int GetRightsGrantedByFriend(UUID principalID, UUID friendID) { - FriendInfo[] friends = GetFriends(principalID); + FriendInfo[] friends = GetFriendsFromCache(principalID); FriendInfo finfo = GetFriend(friends, friendID); if (finfo != null) { @@ -362,7 +355,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Send outstanding friendship offers List outstanding = new List(); - FriendInfo[] friends = GetFriends(agentID); + FriendInfo[] friends = GetFriendsFromCache(agentID); foreach (FriendInfo fi in friends) { if (fi.TheirFlags == -1) @@ -419,7 +412,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { List friendList = new List(); - FriendInfo[] friends = GetFriends(userID); + FriendInfo[] friends = GetFriendsFromCache(userID); foreach (FriendInfo fi in friends) { if (((fi.TheirFlags & (int)FriendRights.CanSeeOnline) != 0) && (fi.TheirFlags != -1)) @@ -492,7 +485,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends /// private void StatusChange(UUID agentID, bool online) { - FriendInfo[] friends = GetFriends(agentID); + FriendInfo[] friends = GetFriendsFromCache(agentID); if (friends.Length > 0) { List friendList = new List(); @@ -564,7 +557,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends m_log.DebugFormat("[FRIENDS]: {0} ({1}) offered friendship to {2} ({3})", principalID, client.FirstName + client.LastName, friendID, im.fromAgentName); // Check that the friendship doesn't exist yet - FriendInfo[] finfos = GetFriends(principalID); + FriendInfo[] finfos = GetFriendsFromCache(principalID); if (finfos != null) { FriendInfo f = GetFriend(finfos, friendID); @@ -729,7 +722,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends "[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, friendID); - FriendInfo[] friends = GetFriends(requester); + FriendInfo[] friends = GetFriendsFromCache(requester); if (friends.Length == 0) { return; @@ -915,20 +908,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion #region Get / Set friends in several flavours - /// - /// Get friends from local cache only - /// - /// - /// - /// An empty array if the user has no friends or friends have not been cached. - /// - protected FriendInfo[] GetFriends(UUID agentID) + + public FriendInfo[] GetFriendsFromCache(UUID userID) { UserFriendData friendsData; lock (m_Friends) { - if (m_Friends.TryGetValue(agentID, out friendsData)) + if (m_Friends.TryGetValue(userID, out friendsData)) return friendsData.Friends; } @@ -946,7 +933,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Update local cache lock (m_Friends) { - FriendInfo[] friends = GetFriends(friendID); + FriendInfo[] friends = GetFriendsFromCache(friendID); FriendInfo finfo = GetFriend(friends, userID); finfo.TheirFlags = rights; } @@ -970,12 +957,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - /// - /// Are friends cached on this simulator for a particular user? - /// - /// - /// - protected bool AreFriendsCached(UUID userID) + public bool AreFriendsCached(UUID userID) { lock (m_Friends) return m_Friends.ContainsKey(userID); @@ -1006,61 +988,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } #endregion - - protected void HandleFriendsShowCacheCommand(string module, string[] cmd) - { - if (cmd.Length != 5) - { - MainConsole.Instance.OutputFormat("Usage: friends show cache [ ]"); - return; - } - - string firstName = cmd[3]; - string lastName = cmd[4]; - - IUserManagement umModule = m_Scenes[0].RequestModuleInterface(); - UUID userId = umModule.GetUserIdByName(firstName, lastName); - -// UserAccount ua -// = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, firstName, lastName); - - if (userId == UUID.Zero) - { - MainConsole.Instance.OutputFormat("No such user as {0} {1}", firstName, lastName); - return; - } - - if (!AreFriendsCached(userId)) - { - MainConsole.Instance.OutputFormat("No friends cached on this simulator for {0} {1}", firstName, lastName); - return; - } - - MainConsole.Instance.OutputFormat("Cached friends for {0} {1}:", firstName, lastName); - - MainConsole.Instance.OutputFormat("UUID\n"); - - FriendInfo[] friends = GetFriends(userId); - - foreach (FriendInfo friend in friends) - { -// MainConsole.Instance.OutputFormat(friend.PrincipalID.ToString()); - -// string friendFirstName, friendLastName; -// -// UserAccount friendUa -// = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friend.PrincipalID); - - UUID friendId; - string friendName; - - if (UUID.TryParse(friend.Friend, out friendId)) - friendName = umModule.GetUserName(friendId); - else - friendName = friend.Friend; - - MainConsole.Instance.OutputFormat("{0} {1} {2}", friendName, friend.MyFlags, friend.TheirFlags); - } - } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index b666daed56..d3a3ee4d8d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -163,7 +163,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId); if (account == null) // foreign { - FriendInfo[] friends = GetFriends(client.AgentId); + FriendInfo[] friends = GetFriendsFromCache(client.AgentId); foreach (FriendInfo f in friends) { client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags); @@ -346,7 +346,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (agentIsLocal) // agent is local, friend is foreigner { - FriendInfo[] finfos = GetFriends(agentID); + FriendInfo[] finfos = GetFriendsFromCache(agentID); FriendInfo finfo = GetFriend(finfos, friendID); if (finfo != null) { @@ -453,7 +453,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends bool confirming = false; if (friendUUI == string.Empty) { - finfos = GetFriends(agentID); + finfos = GetFriendsFromCache(agentID); foreach (FriendInfo finfo in finfos) { if (finfo.TheirFlags == -1) @@ -546,7 +546,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Delete any previous friendship relations FriendInfo[] finfos = null; FriendInfo f = null; - finfos = GetFriends(a1); + finfos = GetFriendsFromCache(a1); if (finfos != null) { f = GetFriend(finfos, a2); @@ -558,7 +558,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - finfos = GetFriends(a2); + finfos = GetFriendsFromCache(a2); if (finfos != null) { f = GetFriend(finfos, a1); @@ -595,7 +595,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (agentIsLocal) // agent is local, 'friend' is foreigner { // We need to look for its information in the friends list itself - FriendInfo[] finfos = GetFriends(agentID); + FriendInfo[] finfos = GetFriendsFromCache(agentID); FriendInfo finfo = GetFriend(finfos, exfriendID); if (finfo != null) { @@ -639,7 +639,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private string GetUUI(UUID localUser, UUID foreignUser) { // Let's see if the user is here by any chance - FriendInfo[] finfos = GetFriends(localUser); + FriendInfo[] finfos = GetFriendsFromCache(localUser); if (finfos != EMPTY_FRIENDS) // friend is here, cool { FriendInfo finfo = GetFriend(finfos, foreignUser); diff --git a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs index 10bef1e2dc..7e87006706 100644 --- a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs @@ -25,14 +25,31 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; -using System.Collections.Generic; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; namespace OpenSim.Region.Framework.Interfaces { public interface IFriendsModule { + /// + /// Are friends cached on this simulator for a particular user? + /// + /// + /// + bool AreFriendsCached(UUID userID); + + /// + /// Get friends from local cache only + /// + /// + /// + /// An empty array if the user has no friends or friends have not been cached. + /// + FriendInfo[] GetFriendsFromCache(UUID userID); + /// /// Add a friendship between two users. /// @@ -58,10 +75,10 @@ namespace OpenSim.Region.Framework.Interfaces /// /// Get permissions granted by a friend. /// - /// The user. - /// The friend that granted. + /// The user. + /// The friend that granted. /// The permissions. These come from the FriendRights enum. - int GetRightsGrantedByFriend(UUID PrincipalID, UUID FriendID); + int GetRightsGrantedByFriend(UUID userID, UUID friendID); /// /// Grant permissions for a friend. diff --git a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs new file mode 100644 index 0000000000..2bcb8a736c --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs @@ -0,0 +1,165 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Statistics; +using OpenSim.Region.ClientStack.LindenUDP; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; + +namespace OpenSim.Region.OptionalModules.Avatar.Friends +{ + /// + /// A module that just holds commands for inspecting avatar appearance. + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "FriendsCommandModule")] + public class FriendsCommandsModule : ISharedRegionModule + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + private IFriendsModule m_friendsModule; + private IUserManagement m_userManagementModule; + +// private IAvatarFactoryModule m_avatarFactory; + + public string Name { get { return "Appearance Information Module"; } } + + public Type ReplaceableInterface { get { return null; } } + + public void Initialise(IConfigSource source) + { +// m_log.DebugFormat("[FRIENDS COMMAND MODULE]: INITIALIZED MODULE"); + } + + public void PostInitialise() + { +// m_log.DebugFormat("[FRIENDS COMMAND MODULE]: POST INITIALIZED MODULE"); + } + + public void Close() + { +// m_log.DebugFormat("[FRIENDS COMMAND MODULE]: CLOSED MODULE"); + } + + public void AddRegion(Scene scene) + { +// m_log.DebugFormat("[FRIENDS COMMANDO MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); + } + + public void RemoveRegion(Scene scene) + { +// m_log.DebugFormat("[FRIENDS COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); + } + + public void RegionLoaded(Scene scene) + { +// m_log.DebugFormat("[APPEARANCE INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); + + if (m_scene == null) + m_scene = scene; + + m_friendsModule = m_scene.RequestModuleInterface(); + m_userManagementModule = m_scene.RequestModuleInterface(); + + if (m_friendsModule != null && m_userManagementModule != null) + { + m_scene.AddCommand( + "Friends", this, "friends show cache", + "friends show cache [ ]", + "Show the friends cache for the given user", + HandleFriendsShowCacheCommand); + } + } + + protected void HandleFriendsShowCacheCommand(string module, string[] cmd) + { + if (cmd.Length != 5) + { + MainConsole.Instance.OutputFormat("Usage: friends show cache [ ]"); + return; + } + + string firstName = cmd[3]; + string lastName = cmd[4]; + + UUID userId = m_userManagementModule.GetUserIdByName(firstName, lastName); + +// UserAccount ua +// = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, firstName, lastName); + + if (userId == UUID.Zero) + { + MainConsole.Instance.OutputFormat("No such user as {0} {1}", firstName, lastName); + return; + } + + if (m_friendsModule.AreFriendsCached(userId)) + { + MainConsole.Instance.OutputFormat("No friends cached on this simulator for {0} {1}", firstName, lastName); + return; + } + + MainConsole.Instance.OutputFormat("Cached friends for {0} {1}:", firstName, lastName); + + MainConsole.Instance.OutputFormat("UUID\n"); + + FriendInfo[] friends = m_friendsModule.GetFriendsFromCache(userId); + + foreach (FriendInfo friend in friends) + { +// MainConsole.Instance.OutputFormat(friend.PrincipalID.ToString()); + +// string friendFirstName, friendLastName; +// +// UserAccount friendUa +// = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friend.PrincipalID); + + UUID friendId; + string friendName; + + if (UUID.TryParse(friend.Friend, out friendId)) + friendName = m_userManagementModule.GetUserName(friendId); + else + friendName = friend.Friend; + + MainConsole.Instance.OutputFormat("{0} {1} {2}", friendName, friend.MyFlags, friend.TheirFlags); + } + } + } +} \ No newline at end of file From 1ef62ca75ef8c551303b4e86e737b5d958d07ce7 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 30 Mar 2012 01:23:34 +0100 Subject: [PATCH 11/21] Lock NullFriendsData.m_Data for consistency and against concurrent read/write --- OpenSim/Data/Null/NullFriendsData.cs | 69 ++++++++++++++++------------ 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/OpenSim/Data/Null/NullFriendsData.cs b/OpenSim/Data/Null/NullFriendsData.cs index 0be32a4ede..473999fdb2 100644 --- a/OpenSim/Data/Null/NullFriendsData.cs +++ b/OpenSim/Data/Null/NullFriendsData.cs @@ -29,6 +29,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Reflection; +using System.Threading; using log4net; using OpenMetaverse; using OpenSim.Framework; @@ -54,7 +55,8 @@ namespace OpenSim.Data.Null /// public static void Clear() { - m_Data.Clear(); + lock (m_Data) + m_Data.Clear(); } public FriendsData[] GetFriends(UUID principalID) @@ -71,27 +73,30 @@ namespace OpenSim.Data.Null /// public FriendsData[] GetFriends(string userID) { - List lst = m_Data.FindAll(fdata => + lock (m_Data) { - return fdata.PrincipalID == userID.ToString(); - }); - - if (lst != null) - { - lst.ForEach(f => + List lst = m_Data.FindAll(fdata => { - FriendsData f2 = m_Data.Find(candidateF2 => f.Friend == candidateF2.PrincipalID); - if (f2 != null) - f.Data["TheirFlags"] = f2.Data["Flags"]; - -// m_log.DebugFormat( -// "[NULL FRIENDS DATA]: Got {0} {1} {2} for {3}", -// f.Friend, f.Data["Flags"], f2 != null ? f.Data["TheirFlags"] : "not found!", f.PrincipalID); + return fdata.PrincipalID == userID.ToString(); }); - -// m_log.DebugFormat("[NULL FRIENDS DATA]: Got {0} friends for {1}", lst.Count, userID); - - return lst.ToArray(); + + if (lst != null) + { + lst.ForEach(f => + { + FriendsData f2 = m_Data.Find(candidateF2 => f.Friend == candidateF2.PrincipalID); + if (f2 != null) + f.Data["TheirFlags"] = f2.Data["Flags"]; + + // m_log.DebugFormat( + // "[NULL FRIENDS DATA]: Got {0} {1} {2} for {3}", + // f.Friend, f.Data["Flags"], f2 != null ? f.Data["TheirFlags"] : "not found!", f.PrincipalID); + }); + + // m_log.DebugFormat("[NULL FRIENDS DATA]: Got {0} friends for {1}", lst.Count, userID); + + return lst.ToArray(); + } } return new FriendsData[0]; @@ -105,7 +110,8 @@ namespace OpenSim.Data.Null // m_log.DebugFormat( // "[NULL FRIENDS DATA]: Storing {0} {1} {2}", data.PrincipalID, data.Friend, data.Data["Flags"]); - m_Data.Add(data); + lock (m_Data) + m_Data.Add(data); return true; } @@ -117,18 +123,21 @@ namespace OpenSim.Data.Null public bool Delete(string userID, string friendID) { - List lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID.ToString(); }); - if (lst != null) + lock (m_Data) { - FriendsData friend = lst.Find(delegate(FriendsData fdata) { return fdata.Friend == friendID; }); - if (friendID != null) + List lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID.ToString(); }); + if (lst != null) { -// m_log.DebugFormat( -// "[NULL FRIENDS DATA]: Deleting friend {0} {1} for {2}", -// friend.Friend, friend.Data["Flags"], friend.PrincipalID); - - m_Data.Remove(friend); - return true; + FriendsData friend = lst.Find(delegate(FriendsData fdata) { return fdata.Friend == friendID; }); + if (friendID != null) + { + // m_log.DebugFormat( + // "[NULL FRIENDS DATA]: Deleting friend {0} {1} for {2}", + // friend.Friend, friend.Data["Flags"], friend.PrincipalID); + + m_Data.Remove(friend); + return true; + } } } From 3525c876c8972fb89a9981d4dc3dcb3220adee9e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 30 Mar 2012 01:57:38 +0100 Subject: [PATCH 12/21] Make default "show friends" console command show friends fetched from the friends service. There is no a --cache option which will show friends from the local cache if available. --- .../Avatar/Friends/FriendsModule.cs | 4 +- .../Avatar/Friends/HGFriendsModule.cs | 3 +- .../Avatar/Friends/FriendsCommandsModule.cs | 87 ++++++++++++++++++- prebuild.xml | 1 + 4 files changed, 87 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 37e6600e4d..f64c161271 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -110,7 +110,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - protected IFriendsService FriendsService + public IFriendsService FriendsService { get { @@ -939,7 +939,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client) + public virtual FriendInfo[] GetFriendsFromService(IClientAPI client) { return FriendsService.GetFriends(client.AgentId); } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index d3a3ee4d8d..9a6d277252 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -300,8 +300,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return null; } - - protected override FriendInfo[] GetFriendsFromService(IClientAPI client) + public override FriendInfo[] GetFriendsFromService(IClientAPI client) { // m_log.DebugFormat("[HGFRIENDS MODULE]: Entering GetFriendsFromService for {0}", client.Name); Boolean agentIsLocal = true; diff --git a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs index 2bcb8a736c..fe737705ea 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs @@ -32,14 +32,17 @@ using System.Reflection; using System.Text; using log4net; using Mono.Addins; +using NDesk.Options; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Framework.Statistics; using OpenSim.Region.ClientStack.LindenUDP; +using OpenSim.Region.CoreModules.Avatar.Friends; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; namespace OpenSim.Region.OptionalModules.Avatar.Friends @@ -100,10 +103,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends if (m_friendsModule != null && m_userManagementModule != null) { m_scene.AddCommand( - "Friends", this, "friends show cache", - "friends show cache [ ]", - "Show the friends cache for the given user", - HandleFriendsShowCacheCommand); + "Friends", this, "friends show", + "friends show [--cache] ", + "Show the friends for the given user if they exist.\n", + "The --cache option will show locally cached information for that user.", + HandleFriendsShowCommand); } } @@ -161,5 +165,80 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends MainConsole.Instance.OutputFormat("{0} {1} {2}", friendName, friend.MyFlags, friend.TheirFlags); } } + + protected void HandleFriendsShowCommand(string module, string[] cmd) + { + Dictionary options = new Dictionary(); + OptionSet optionSet = new OptionSet().Add("c|cache", delegate (string v) { options["cache"] = v != null; }); + + List mainParams = optionSet.Parse(cmd); + + if (mainParams.Count != 4) + { + MainConsole.Instance.OutputFormat("Usage: friends show [--cache] "); + return; + } + + string firstName = mainParams[2]; + string lastName = mainParams[3]; + + UUID userId = m_userManagementModule.GetUserIdByName(firstName, lastName); + +// UserAccount ua +// = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, firstName, lastName); + + if (userId == UUID.Zero) + { + MainConsole.Instance.OutputFormat("No such user as {0} {1}", firstName, lastName); + return; + } + + FriendInfo[] friends; + + if (options.ContainsKey("cache")) + { + if (!m_friendsModule.AreFriendsCached(userId)) + { + MainConsole.Instance.OutputFormat("No friends cached on this simulator for {0} {1}", firstName, lastName); + return; + } + else + { + friends = m_friendsModule.GetFriendsFromCache(userId); + } + } + else + { + // FIXME: We're forced to do this right now because IFriendsService has no region connectors. We can't + // just expose FriendsModule.GetFriendsFromService() because it forces an IClientAPI requirement that + // can't currently be changed because of HGFriendsModule code that takes the scene from the client. + friends = ((FriendsModule)m_friendsModule).FriendsService.GetFriends(userId); + } + + MainConsole.Instance.OutputFormat("Friends for {0} {1} {2}:", firstName, lastName, userId); + + MainConsole.Instance.OutputFormat("UUID, Name, MyFlags, TheirFlags"); + + foreach (FriendInfo friend in friends) + { +// MainConsole.Instance.OutputFormat(friend.PrincipalID.ToString()); + +// string friendFirstName, friendLastName; +// +// UserAccount friendUa +// = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friend.PrincipalID); + + UUID friendId; + string friendName; + + if (UUID.TryParse(friend.Friend, out friendId)) + friendName = m_userManagementModule.GetUserName(friendId); + else + friendName = friend.Friend; + + MainConsole.Instance.OutputFormat( + "{0} {1} {2} {3}", friend.Friend, friendName, friend.MyFlags, friend.TheirFlags); + } + } } } \ No newline at end of file diff --git a/prebuild.xml b/prebuild.xml index 4ceb137b1d..4f04032e2a 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1669,6 +1669,7 @@ + From 269e479cdc25c5420b4feaaebc233933323f93e2 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 30 Mar 2012 02:00:01 +0100 Subject: [PATCH 13/21] minor: remove some now unneeded code from FriendsCommandsModule --- .../Avatar/Friends/FriendsCommandsModule.cs | 55 ------------------- 1 file changed, 55 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs index fe737705ea..e68f9d07a3 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs @@ -111,61 +111,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends } } - protected void HandleFriendsShowCacheCommand(string module, string[] cmd) - { - if (cmd.Length != 5) - { - MainConsole.Instance.OutputFormat("Usage: friends show cache [ ]"); - return; - } - - string firstName = cmd[3]; - string lastName = cmd[4]; - - UUID userId = m_userManagementModule.GetUserIdByName(firstName, lastName); - -// UserAccount ua -// = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, firstName, lastName); - - if (userId == UUID.Zero) - { - MainConsole.Instance.OutputFormat("No such user as {0} {1}", firstName, lastName); - return; - } - - if (m_friendsModule.AreFriendsCached(userId)) - { - MainConsole.Instance.OutputFormat("No friends cached on this simulator for {0} {1}", firstName, lastName); - return; - } - - MainConsole.Instance.OutputFormat("Cached friends for {0} {1}:", firstName, lastName); - - MainConsole.Instance.OutputFormat("UUID\n"); - - FriendInfo[] friends = m_friendsModule.GetFriendsFromCache(userId); - - foreach (FriendInfo friend in friends) - { -// MainConsole.Instance.OutputFormat(friend.PrincipalID.ToString()); - -// string friendFirstName, friendLastName; -// -// UserAccount friendUa -// = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friend.PrincipalID); - - UUID friendId; - string friendName; - - if (UUID.TryParse(friend.Friend, out friendId)) - friendName = m_userManagementModule.GetUserName(friendId); - else - friendName = friend.Friend; - - MainConsole.Instance.OutputFormat("{0} {1} {2}", friendName, friend.MyFlags, friend.TheirFlags); - } - } - protected void HandleFriendsShowCommand(string module, string[] cmd) { Dictionary options = new Dictionary(); From e5343bccdf4f422dc6cf93a38038a045813f827e Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 30 Mar 2012 02:11:32 +0100 Subject: [PATCH 14/21] Add Extended flavour option to opensim version information. This flavour is for changes in addition to the 0.7.3-post-fixes branch that are too large to be considered fixes but should be reasonably stable. This flavour will almost certainly never see a formal release. --- OpenSim/Framework/Servers/VersionInfo.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index 7a5d7158d6..5f01788b62 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -39,7 +39,8 @@ namespace OpenSim RC1, RC2, Release, - Post_Fixes + Post_Fixes, + Extended } public static string Version From 5a8ed5063925da291b7c7af8172310ef255189a8 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 30 Mar 2012 12:39:45 -0700 Subject: [PATCH 15/21] Added missing dependency for MS 2008. I hope. (I don't have 2008 to test this) mantis #5949 --- prebuild.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/prebuild.xml b/prebuild.xml index 4f04032e2a..a8b735ccf4 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1230,6 +1230,7 @@ ../../../bin/ + From 874140f950add3b698a3c75ab24727e62e83f329 Mon Sep 17 00:00:00 2001 From: PixelTomsen Date: Wed, 14 Mar 2012 23:33:22 +0100 Subject: [PATCH 16/21] fix Infinite loading on No Rez http://opensimulator.org/mantis/view.php?id=5932 --- .../Framework/InventoryAccess/InventoryAccessModule.cs | 5 +++++ OpenSim/Region/Framework/Scenes/Scene.cs | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index d320af4b81..1c84e7756f 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -935,6 +935,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment)) remoteClient.SendBulkUpdateInventory(item); + ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); + remoteClient.SendAlertMessage(string.Format( + "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.", + item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknow", m_Scene.RegionInfo.RegionName)); + return false; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 44cd30a70b..954b76f129 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1971,10 +1971,16 @@ namespace OpenSim.Region.Framework.Scenes if (Permissions.CanRezObject(1, ownerID, pos)) { // rez ON the ground, not IN the ground - // pos.Z += 0.25F; The rez point should now be correct so that its not in the ground + // pos.Z += 0.25F; The rez point should now be correct so that its not in the ground AddNewPrim(ownerID, groupID, pos, rot, shape); } + else + { + IClientAPI client = null; + if (this.TryGetClient(ownerID, out client)) + client.SendAlertMessage("You cannot create objects here."); + } } public virtual SceneObjectGroup AddNewPrim( From 69fc8c4985ebb9e205b86114b7c4e3dd4063153b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 31 Mar 2012 01:07:14 +0100 Subject: [PATCH 17/21] minor: small message adjustment and unnecessary code elimination when notifying client of no build permission --- .../Framework/InventoryAccess/InventoryAccessModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 1c84e7756f..4dd89d2e88 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -938,7 +938,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); remoteClient.SendAlertMessage(string.Format( "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.", - item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknow", m_Scene.RegionInfo.RegionName)); + item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.RegionInfo.RegionName)); return false; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 954b76f129..fc615718e0 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1978,7 +1978,7 @@ namespace OpenSim.Region.Framework.Scenes else { IClientAPI client = null; - if (this.TryGetClient(ownerID, out client)) + if (TryGetClient(ownerID, out client)) client.SendAlertMessage("You cannot create objects here."); } } From 38d241a3177f07e6640292ca4e94341e221992a4 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 31 Mar 2012 01:12:04 +0100 Subject: [PATCH 18/21] Add MSSQL login processing fix for servers run on different locales. This may no longer be an issue with better locale enforcement in OpenSimulator but it doesn't hurt to have this patch. http://opensimulator.org/mantis/view.php?id=4680 Thanks to controlbreak for this --- CONTRIBUTORS.txt | 1 + OpenSim/Data/MSSQL/MSSQLManager.cs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 089d2f544c..287073bbf8 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -71,6 +71,7 @@ what it is today. * CharlieO * ChrisDown * Chris Yeoh (IBM) +* controlbreak * coyled * Daedius * Dong Jun Lan (IBM) diff --git a/OpenSim/Data/MSSQL/MSSQLManager.cs b/OpenSim/Data/MSSQL/MSSQLManager.cs index cf963e3f07..9a0015c857 100644 --- a/OpenSim/Data/MSSQL/MSSQLManager.cs +++ b/OpenSim/Data/MSSQL/MSSQLManager.cs @@ -104,6 +104,11 @@ namespace OpenSim.Data.MSSQL { return SqlDbType.BigInt; } + if (type == typeof(DateTime)) + { + return SqlDbType.DateTime; + } + return SqlDbType.VarChar; } From 387d7fdad56267b845c12a52cbc6b80c56c8a558 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 31 Mar 2012 01:29:13 +0100 Subject: [PATCH 19/21] Allow llRegionSayTo() to work on the PUBLIC_CHANNEL, as per http://wiki.secondlife.com/wiki/LlRegionSayTo Addresses http://opensimulator.org/mantis/view.php?id=5950 --- .../Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index ef9b4e069b..176c86de12 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -319,7 +319,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm // Send message to avatar if (channel == 0) { - m_scene.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0, pos, name, id, false); + m_scene.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, false); } List attachments = sp.GetAttachments(); From f0406f9fe2f7a1d4d135934280735a3fdc41935f Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 31 Mar 2012 01:45:37 +0100 Subject: [PATCH 20/21] Rename SOG.HasChildPrim(uint) to SOG.ContainsPart(uint) to match existing ContainsPart method and remove method duplication. HasChildPrim is also misleading since the 'root' prim can also be returned. --- OpenSim/Data/Tests/RegionTests.cs | 8 ++-- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 6 +-- .../Framework/Scenes/SceneObjectGroup.cs | 47 +++++++------------ .../Shared/Api/Implementation/LSL_Api.cs | 6 +-- 4 files changed, 28 insertions(+), 39 deletions(-) diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index 1d806fc5eb..1f03ec5c20 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -244,10 +244,10 @@ namespace OpenSim.Data.Tests SceneObjectPart[] newparts = newsog.Parts; Assert.That(newparts.Length,Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))"); - Assert.That(newsog.HasChildPrim(tmp0), "Assert.That(newsog.HasChildPrim(tmp0))"); - Assert.That(newsog.HasChildPrim(tmp1), "Assert.That(newsog.HasChildPrim(tmp1))"); - Assert.That(newsog.HasChildPrim(tmp2), "Assert.That(newsog.HasChildPrim(tmp2))"); - Assert.That(newsog.HasChildPrim(tmp3), "Assert.That(newsog.HasChildPrim(tmp3))"); + Assert.That(newsog.ContainsPart(tmp0), "Assert.That(newsog.ContainsPart(tmp0))"); + Assert.That(newsog.ContainsPart(tmp1), "Assert.That(newsog.ContainsPart(tmp1))"); + Assert.That(newsog.ContainsPart(tmp2), "Assert.That(newsog.ContainsPart(tmp2))"); + Assert.That(newsog.ContainsPart(tmp3), "Assert.That(newsog.ContainsPart(tmp3))"); } [Test] diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 5c542d65a2..cd1366c107 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -860,7 +860,7 @@ namespace OpenSim.Region.Framework.Scenes if (sog != null) { - if (sog.HasChildPrim(localID)) + if (sog.ContainsPart(localID)) { // m_log.DebugFormat( // "[SCENE GRAPH]: Found scene object {0} {1} {2} containing part with local id {3} in {4}. Returning.", @@ -888,7 +888,7 @@ namespace OpenSim.Region.Framework.Scenes if (ent is SceneObjectGroup) { sog = (SceneObjectGroup)ent; - if (sog.HasChildPrim(localID)) + if (sog.ContainsPart(localID)) { lock (SceneObjectGroupsByLocalPartID) SceneObjectGroupsByLocalPartID[localID] = sog; @@ -926,7 +926,7 @@ namespace OpenSim.Region.Framework.Scenes if (ent is SceneObjectGroup) { sog = (SceneObjectGroup)ent; - if (sog.HasChildPrim(fullID)) + if (sog.ContainsPart(fullID)) { lock (SceneObjectGroupsByFullPartID) SceneObjectGroupsByFullPartID[fullID] = sog; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index afb5ccfae5..9d16bebabf 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -338,6 +338,24 @@ namespace OpenSim.Region.Framework.Scenes return m_parts.ContainsKey(partID); } + /// + /// Does this group contain the given part? + /// should be able to remove these methods once we have a entity index in scene + /// + /// + /// + public bool ContainsPart(uint localID) + { + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + { + if (parts[i].LocalId == localID) + return true; + } + + return false; + } + /// /// The root part of this scene object /// @@ -1911,35 +1929,6 @@ namespace OpenSim.Region.Framework.Scenes return null; } - /// - /// Does this group contain the child prim - /// should be able to remove these methods once we have a entity index in scene - /// - /// - /// - public bool HasChildPrim(UUID primID) - { - return m_parts.ContainsKey(primID); - } - - /// - /// Does this group contain the child prim - /// should be able to remove these methods once we have a entity index in scene - /// - /// - /// - public bool HasChildPrim(uint localID) - { - SceneObjectPart[] parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - { - if (parts[i].LocalId == localID) - return true; - } - - return false; - } - #endregion #region Packet Handlers diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 745592940d..b502ab8f6e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3763,7 +3763,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // parse for sitting avatare-uuids World.ForEachRootScenePresence(delegate(ScenePresence presence) { - if (presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID)) + if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID)) keytable.Add(presence.UUID); }); @@ -3826,7 +3826,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api World.ForEachRootScenePresence(delegate(ScenePresence presence) { SceneObjectPart sitPart = presence.ParentPart; - if (sitPart != null && m_host.ParentGroup.HasChildPrim(sitPart.LocalId)) + if (sitPart != null && m_host.ParentGroup.ContainsPart(sitPart.LocalId)) nametable.Add(presence.ControllingClient.Name); }); @@ -7684,7 +7684,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api int avatarCount = 0; World.ForEachRootScenePresence(delegate(ScenePresence presence) { - if (presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID)) + if (presence.ParentID != 0 && m_host.ParentGroup.ContainsPart(presence.ParentID)) avatarCount++; }); From 32a953fed727fdadd65228b7c9282091da3521ac Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 31 Mar 2012 01:52:06 +0100 Subject: [PATCH 21/21] refactor: Rename SOG.GetChildPart() to GetPart() since it can also return the 'root' part. --- .../World/Vegetation/VegetationModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 4 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 4 +- .../Scenes/SceneObjectGroup.Inventory.cs | 8 ++-- .../Framework/Scenes/SceneObjectGroup.cs | 40 +++++++++---------- .../Scenes/SceneObjectPartInventory.cs | 2 +- .../TreePopulator/TreePopulatorModule.cs | 2 +- 7 files changed, 31 insertions(+), 31 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs index ab8e1bf0b7..f5f35bb92e 100644 --- a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs +++ b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs @@ -79,7 +79,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Vegetation } SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); - SceneObjectPart rootPart = sceneObject.GetChildPart(sceneObject.UUID); + SceneObjectPart rootPart = sceneObject.GetPart(sceneObject.UUID); // if grass or tree, make phantom //rootPart.TrimPermissions(); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index fc615718e0..06f7c0f64a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1833,7 +1833,7 @@ namespace OpenSim.Region.Framework.Scenes { AddRestoredSceneObject(group, true, true); EventManager.TriggerOnSceneObjectLoaded(group); - SceneObjectPart rootPart = group.GetChildPart(group.UUID); + SceneObjectPart rootPart = group.GetPart(group.UUID); rootPart.Flags &= ~PrimFlags.Scripted; rootPart.TrimPermissions(); @@ -4174,7 +4174,7 @@ namespace OpenSim.Region.Framework.Scenes { if (ent is SceneObjectGroup) { - SceneObjectPart part = ((SceneObjectGroup)ent).GetChildPart(((SceneObjectGroup)ent).UUID); + SceneObjectPart part = ((SceneObjectGroup)ent).GetPart(((SceneObjectGroup)ent).UUID); if (part != null) { if (part.Name == cmdparams[2]) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index cd1366c107..8a05772c61 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1015,7 +1015,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group == null) return null; - return group.GetChildPart(localID); + return group.GetPart(localID); } /// @@ -1062,7 +1062,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(fullID); if (group == null) return null; - return group.GetChildPart(fullID); + return group.GetPart(fullID); } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index a73d9b69f9..10012d016a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -96,7 +96,7 @@ namespace OpenSim.Region.Framework.Scenes UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID; - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { TaskInventoryItem taskItem = new TaskInventoryItem(); @@ -170,7 +170,7 @@ namespace OpenSim.Region.Framework.Scenes /// null if the item does not exist public TaskInventoryItem GetInventoryItem(uint primID, UUID itemID) { - SceneObjectPart part = GetChildPart(primID); + SceneObjectPart part = GetPart(primID); if (part != null) { return part.Inventory.GetInventoryItem(itemID); @@ -194,7 +194,7 @@ namespace OpenSim.Region.Framework.Scenes /// false if the item did not exist, true if the update occurred succesfully public bool UpdateInventoryItem(TaskInventoryItem item) { - SceneObjectPart part = GetChildPart(item.ParentPartID); + SceneObjectPart part = GetPart(item.ParentPartID); if (part != null) { part.Inventory.UpdateInventoryItem(item); @@ -214,7 +214,7 @@ namespace OpenSim.Region.Framework.Scenes public int RemoveInventoryItem(uint localID, UUID itemID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { int type = part.Inventory.RemoveInventoryItem(itemID); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 9d16bebabf..04b3766b15 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1127,7 +1127,7 @@ namespace OpenSim.Region.Framework.Scenes public UUID GetPartsFullID(uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { return part.UUID; @@ -1143,7 +1143,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - SceneObjectPart part = GetChildPart(localId); + SceneObjectPart part = GetPart(localId); OnGrabPart(part, offsetPos, remoteClient); } } @@ -1904,8 +1904,8 @@ namespace OpenSim.Region.Framework.Scenes /// Get a part with a given UUID /// /// - /// null if a child part with the primID was not found - public SceneObjectPart GetChildPart(UUID primID) + /// null if a part with the primID was not found + public SceneObjectPart GetPart(UUID primID) { SceneObjectPart childPart; m_parts.TryGetValue(primID, out childPart); @@ -1916,8 +1916,8 @@ namespace OpenSim.Region.Framework.Scenes /// Get a part with a given local ID /// /// - /// null if a child part with the local ID was not found - public SceneObjectPart GetChildPart(uint localID) + /// null if a part with the local ID was not found + public SceneObjectPart GetPart(uint localID) { SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) @@ -2035,7 +2035,7 @@ namespace OpenSim.Region.Framework.Scenes /// The object group of the newly delinked prim. Null if part could not be found public SceneObjectGroup DelinkFromGroup(uint partID, bool sendEvents) { - SceneObjectPart linkPart = GetChildPart(partID); + SceneObjectPart linkPart = GetPart(partID); if (linkPart != null) { @@ -2326,7 +2326,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void SetPartName(string name, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { part.Name = name; @@ -2335,7 +2335,7 @@ namespace OpenSim.Region.Framework.Scenes public void SetPartDescription(string des, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { part.Description = des; @@ -2344,7 +2344,7 @@ namespace OpenSim.Region.Framework.Scenes public void SetPartText(string text, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { part.SetText(text); @@ -2353,7 +2353,7 @@ namespace OpenSim.Region.Framework.Scenes public void SetPartText(string text, UUID partID) { - SceneObjectPart part = GetChildPart(partID); + SceneObjectPart part = GetPart(partID); if (part != null) { part.SetText(text); @@ -2362,7 +2362,7 @@ namespace OpenSim.Region.Framework.Scenes public string GetPartName(uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { return part.Name; @@ -2372,7 +2372,7 @@ namespace OpenSim.Region.Framework.Scenes public string GetPartDescription(uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { return part.Description; @@ -2390,7 +2390,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) { - SceneObjectPart selectionPart = GetChildPart(localID); + SceneObjectPart selectionPart = GetPart(localID); if (SetTemporary && Scene != null) { @@ -2427,7 +2427,7 @@ namespace OpenSim.Region.Framework.Scenes public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { part.UpdateExtraParam(type, inUse, data); @@ -2441,7 +2441,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateTextureEntry(uint localID, byte[] textureEntry) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { part.UpdateTextureEntry(textureEntry); @@ -2473,7 +2473,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { part.UpdateShape(shapeBlock); @@ -2685,7 +2685,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateSinglePosition(Vector3 pos, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); // SceneObjectPart[] parts = m_parts.GetArray(); // for (int i = 0; i < parts.Length; i++) @@ -2824,7 +2824,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateSingleRotation(Quaternion rot, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) @@ -2853,7 +2853,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateSingleRotation(Quaternion rot, Vector3 pos, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { // m_log.DebugFormat( diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 71a9084fe7..f7e123b97b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -623,7 +623,7 @@ namespace OpenSim.Region.Framework.Scenes group.ResetIDs(); - SceneObjectPart rootPart = group.GetChildPart(group.UUID); + SceneObjectPart rootPart = group.GetPart(group.UUID); // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs index a17eb41740..51b0592356 100644 --- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs +++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs @@ -510,7 +510,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator } SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); - SceneObjectPart rootPart = sceneObject.GetChildPart(sceneObject.UUID); + SceneObjectPart rootPart = sceneObject.GetPart(sceneObject.UUID); rootPart.AddFlag(PrimFlags.Phantom);