From 5c5966545d14de43500b95109e8ce81058ebe2c3 Mon Sep 17 00:00:00 2001
From: Diva Canto
Date: Sun, 28 Feb 2010 12:07:38 -0800
Subject: Initial Online friends notification seems to be working reliably now.
 All this needs more testing, but everything is there.

---
 OpenSim/Client/MXP/ClientStack/MXPClientView.cs    |  4 +-
 .../Sirikata/ClientStack/SirikataClientView.cs     |  2 +-
 .../Client/VWoHTTP/ClientStack/VWHClientView.cs    |  2 +-
 OpenSim/Framework/IClientAPI.cs                    |  4 +-
 .../Region/ClientStack/LindenUDP/LLClientView.cs   |  6 +--
 .../CoreModules/Avatar/Friends/FriendsModule.cs    | 54 +++++++++++++++-------
 .../Region/Examples/SimpleModule/MyNpcCharacter.cs |  4 +-
 .../Region/Framework/Interfaces/IFriendsModule.cs  |  1 +
 OpenSim/Region/Framework/Scenes/EventManager.cs    | 27 ++++++++++-
 OpenSim/Region/Framework/Scenes/Scene.cs           |  6 ++-
 OpenSim/Region/Framework/Scenes/ScenePresence.cs   |  6 ++-
 .../Server/IRCClientView.cs                        |  4 +-
 .../Region/OptionalModules/World/NPC/NPCAvatar.cs  |  4 +-
 OpenSim/Tests/Common/Mock/TestClient.cs            |  6 +--
 14 files changed, 94 insertions(+), 36 deletions(-)

diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
index fcd16b8..167a40c 100644
--- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
+++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
@@ -597,7 +597,7 @@ namespace OpenSim.Client.MXP.ClientStack
         public event DeRezObject OnDeRezObject;
         public event Action<IClientAPI> OnRegionHandShakeReply;
         public event GenericCall2 OnRequestWearables;
-        public event GenericCall2 OnCompleteMovementToRegion;
+        public event GenericCall1 OnCompleteMovementToRegion;
         public event UpdateAgent OnAgentUpdate;
         public event AgentRequestSit OnAgentRequestSit;
         public event AgentSit OnAgentSit;
@@ -906,7 +906,7 @@ namespace OpenSim.Client.MXP.ClientStack
 
             if (OnCompleteMovementToRegion != null)
             {
-                OnCompleteMovementToRegion();
+                OnCompleteMovementToRegion(this);
             }
 
             // Need to translate to MXP somehow
diff --git a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs
index 208065c..6185164 100644
--- a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs
+++ b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs
@@ -243,7 +243,7 @@ namespace OpenSim.Client.Sirikata.ClientStack
         public event DeRezObject OnDeRezObject;
         public event Action<IClientAPI> OnRegionHandShakeReply;
         public event GenericCall2 OnRequestWearables;
-        public event GenericCall2 OnCompleteMovementToRegion;
+        public event GenericCall1 OnCompleteMovementToRegion;
         public event UpdateAgent OnAgentUpdate;
         public event AgentRequestSit OnAgentRequestSit;
         public event AgentSit OnAgentSit;
diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
index 2b1b11f..7a32e7f 100644
--- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
+++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
@@ -246,7 +246,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
         public event DeRezObject OnDeRezObject = delegate { };
         public event Action<IClientAPI> OnRegionHandShakeReply = delegate { };
         public event GenericCall2 OnRequestWearables = delegate { };
-        public event GenericCall2 OnCompleteMovementToRegion = delegate { };
+        public event GenericCall1 OnCompleteMovementToRegion = delegate { };
         public event UpdateAgent OnAgentUpdate = delegate { };
         public event AgentRequestSit OnAgentRequestSit = delegate { };
         public event AgentSit OnAgentSit = delegate { };
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 10a091a..4003b7e 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -93,6 +93,8 @@ namespace OpenSim.Framework
 
     public delegate void SetAlwaysRun(IClientAPI remoteClient, bool SetAlwaysRun);
 
+    public delegate void GenericCall1(IClientAPI remoteClient);
+
     public delegate void GenericCall2();
 
     // really don't want to be passing packets in these events, so this is very temporary.
@@ -878,7 +880,7 @@ namespace OpenSim.Framework
         event DeRezObject OnDeRezObject;
         event Action<IClientAPI> OnRegionHandShakeReply;
         event GenericCall2 OnRequestWearables;
-        event GenericCall2 OnCompleteMovementToRegion;
+        event GenericCall1 OnCompleteMovementToRegion;
         event UpdateAgent OnAgentUpdate;
         event AgentRequestSit OnAgentRequestSit;
         event AgentSit OnAgentSit;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index afc5270..c185640 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -121,7 +121,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
         public event ObjectAttach OnObjectAttach;
         public event ObjectDeselect OnObjectDetach;
         public event ObjectDrop OnObjectDrop;
-        public event GenericCall2 OnCompleteMovementToRegion;
+        public event GenericCall1 OnCompleteMovementToRegion;
         public event UpdateAgent OnAgentUpdate;
         public event AgentRequestSit OnAgentRequestSit;
         public event AgentSit OnAgentSit;
@@ -5737,10 +5737,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
         private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack)
         {
-            GenericCall2 handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
+            GenericCall1 handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
             if (handlerCompleteMovementToRegion != null)
             {
-                handlerCompleteMovementToRegion();
+                handlerCompleteMovementToRegion(sender);
             }
             handlerCompleteMovementToRegion = null;
 
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index cc3a3ee..8aa5b91 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -79,6 +79,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
         protected Dictionary<UUID, UserFriendData> m_Friends =
                 new Dictionary<UUID, UserFriendData>();
 
+        protected List<UUID> m_NeedsListOfFriends = new List<UUID>();
+
         protected IPresenceService PresenceService
         {
             get
@@ -170,6 +172,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             scene.EventManager.OnClientClosed += OnClientClosed;
             scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
             scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
+            scene.EventManager.OnClientLogin += OnClientLogin;
         }
 
         public void RegionLoaded(Scene scene)
@@ -220,7 +223,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             client.OnGrantUserRights += OnGrantUserRights;
 
             client.OnLogout += OnLogout;
-            client.OnEconomyDataRequest += SendPresence;
 
             if (m_Friends.ContainsKey(client.AgentId))
             {
@@ -285,30 +287,50 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
             }
         }
 
-        private void SendPresence(UUID agentID)
+        private void OnClientLogin(IClientAPI client)
         {
+            UUID agentID = client.AgentId;
+
             // Inform the friends that this user is online
             StatusChange(agentID, true);
             
-            // Now send the list of online friends to this user
-            if (!m_Friends.ContainsKey(agentID))
-            {
-                m_log.DebugFormat("[FRIENDS MODULE]: agent {0} not found in local cache", agentID);
-                return;
-            }
+            // Register that we need to send the list of online friends to this user
+            lock (m_NeedsListOfFriends)
+                if (!m_NeedsListOfFriends.Contains(agentID))
+                {
+                    m_NeedsListOfFriends.Add(agentID);
+                }
+        }
 
-            IClientAPI client = LocateClientObject(agentID);
-            if (client == null)
+        public void SendFriendsOnlineIfNeeded(IClientAPI client)
+        {
+            UUID agentID = client.AgentId;
+            if (m_NeedsListOfFriends.Contains(agentID))
             {
-                m_log.DebugFormat("[FRIENDS MODULE]: agent's client {0} not found in local scene", agentID);
-                return;
-            }
+                if (!m_Friends.ContainsKey(agentID))
+                {
+                    m_log.DebugFormat("[FRIENDS MODULE]: agent {0} not found in local cache", agentID);
+                    return;
+                }
+
+                client = LocateClientObject(agentID);
+                if (client == null)
+                {
+                    m_log.DebugFormat("[FRIENDS MODULE]: agent's client {0} not found in local scene", agentID);
+                    return;
+                }
 
-            List<UUID> online = GetOnlineFriends(agentID);
+                List<UUID> online = GetOnlineFriends(agentID);
 
-            m_log.DebugFormat("[FRIENDS]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count);
-            client.SendAgentOnline(online.ToArray());
+                if (online.Count > 0)
+                {
+                    m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count);
+                    client.SendAgentOnline(online.ToArray());
+                }
 
+                lock (m_NeedsListOfFriends)
+                    m_NeedsListOfFriends.Remove(agentID);
+            }
         }
 
         List<UUID> GetOnlineFriends(UUID userID)
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index 2c5c6e9..bb0d43b 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -83,7 +83,7 @@ namespace OpenSim.Region.Examples.SimpleModule
         public event DeRezObject OnDeRezObject;
         public event Action<IClientAPI> OnRegionHandShakeReply;
         public event GenericCall2 OnRequestWearables;
-        public event GenericCall2 OnCompleteMovementToRegion;
+        public event GenericCall1 OnCompleteMovementToRegion;
         public event UpdateAgent OnAgentUpdate;
         public event AgentRequestSit OnAgentRequestSit;
         public event AgentSit OnAgentSit;
@@ -659,7 +659,7 @@ namespace OpenSim.Region.Examples.SimpleModule
 
             if (OnCompleteMovementToRegion != null)
             {
-                OnCompleteMovementToRegion();
+                OnCompleteMovementToRegion(this);
             }
         }
         public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
diff --git a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
index 239a2ba..a0a1e3a 100644
--- a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
@@ -47,5 +47,6 @@ namespace OpenSim.Region.Framework.Interfaces
         /// <param name="offerMessage"></param>
         void OfferFriendship(UUID fromUserId, IClientAPI toUserClient, string offerMessage);
         uint GetFriendPerms(UUID PrincipalID, UUID FriendID);
+        void SendFriendsOnlineIfNeeded(IClientAPI client);
     }
 }
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 57e1c37..ac04462 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -66,13 +66,16 @@ namespace OpenSim.Region.Framework.Scenes
         public event OnClientConnectCoreDelegate OnClientConnect;
 
         public delegate void OnNewClientDelegate(IClientAPI client);
-
+        
         /// <summary>
         /// Deprecated in favour of OnClientConnect.
         /// Will be marked Obsolete after IClientCore has 100% of IClientAPI interfaces.
         /// </summary>
         public event OnNewClientDelegate OnNewClient;
 
+        public delegate void OnClientLoginDelegate(IClientAPI client);
+        public event OnClientLoginDelegate OnClientLogin;
+
         public delegate void OnNewPresenceDelegate(ScenePresence presence);
 
         public event OnNewPresenceDelegate OnNewPresence;
@@ -583,6 +586,28 @@ namespace OpenSim.Region.Framework.Scenes
             }
         }
 
+        public void TriggerOnClientLogin(IClientAPI client)
+        {
+            OnClientLoginDelegate handlerClientLogin = OnClientLogin;
+            if (handlerClientLogin != null)
+            {
+                foreach (OnClientLoginDelegate d in handlerClientLogin.GetInvocationList())
+                {
+                    try
+                    {
+                        d(client);
+                    }
+                    catch (Exception e)
+                    {
+                        m_log.ErrorFormat(
+                            "[EVENT MANAGER]: Delegate for TriggerOnClientLogin failed - continuing.  {0} {1}",
+                            e.Message, e.StackTrace);
+                    }
+                }
+            }
+
+        }
+
         public void TriggerOnNewPresence(ScenePresence presence)
         {
             OnNewPresenceDelegate handlerNewPresence = OnNewPresence;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index b9b16ad..d00c990 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -2422,6 +2422,8 @@ namespace OpenSim.Region.Framework.Scenes
         /// <param name="client"></param>
         public override void AddNewClient(IClientAPI client)
         {
+            bool vialogin = false;
+
             m_clientManager.Add(client);
 
             CheckHeartbeat();
@@ -2463,6 +2465,7 @@ namespace OpenSim.Region.Framework.Scenes
                     if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0)
                     {
                         m_log.DebugFormat("[Scene]: Incoming client {0} {1} in region {2} via Login", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName);
+                        vialogin = true;
                         IUserAgentVerificationModule userVerification = RequestModuleInterface<IUserAgentVerificationModule>();
                         if (userVerification != null)
                         {
@@ -2512,7 +2515,8 @@ namespace OpenSim.Region.Framework.Scenes
 
             m_LastLogin = Util.EnvironmentTickCount();
             EventManager.TriggerOnNewClient(client);
-
+            if (vialogin)
+                EventManager.TriggerOnClientLogin(client);
         }
 
         
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index af9afa6..f83a4d2 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1114,7 +1114,7 @@ namespace OpenSim.Region.Framework.Scenes
         /// This is called upon a very important packet sent from the client,
         /// so it's client-controlled. Never call this method directly.
         /// </summary>
-        public void CompleteMovement()
+        public void CompleteMovement(IClientAPI client)
         {
             //m_log.Debug("[SCENE PRESENCE]: CompleteMovement");
 
@@ -1159,6 +1159,10 @@ namespace OpenSim.Region.Framework.Scenes
                     m_agentTransfer.EnableChildAgents(this);
                 else
                     m_log.DebugFormat("[SCENE PRESENCE]: Unable to create child agents in neighbours, because AgentTransferModule is not active");
+
+                IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
+                if (friendsModule != null)
+                    friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
             }
 
         }
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index f54733d..92e5a13 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -679,7 +679,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
         public event DeRezObject OnDeRezObject;
         public event Action<IClientAPI> OnRegionHandShakeReply;
         public event GenericCall2 OnRequestWearables;
-        public event GenericCall2 OnCompleteMovementToRegion;
+        public event GenericCall1 OnCompleteMovementToRegion;
         public event UpdateAgent OnAgentUpdate;
         public event AgentRequestSit OnAgentRequestSit;
         public event AgentSit OnAgentSit;
@@ -913,7 +913,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
 
             if (OnCompleteMovementToRegion != null)
             {
-                OnCompleteMovementToRegion();
+                OnCompleteMovementToRegion(this);
             }
         }
 
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index ea46945..17453f1 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -189,7 +189,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
         public event DeRezObject OnDeRezObject;
         public event Action<IClientAPI> OnRegionHandShakeReply;
         public event GenericCall2 OnRequestWearables;
-        public event GenericCall2 OnCompleteMovementToRegion;
+        public event GenericCall1 OnCompleteMovementToRegion;
         public event UpdateAgent OnAgentUpdate;
         public event AgentRequestSit OnAgentRequestSit;
         public event AgentSit OnAgentSit;
@@ -744,7 +744,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
 
             if (OnCompleteMovementToRegion != null)
             {
-                OnCompleteMovementToRegion();
+                OnCompleteMovementToRegion(this);
             }
         }
         public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 873b3ac..803b352 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -95,7 +95,7 @@ namespace OpenSim.Tests.Common.Mock
         public event DeRezObject OnDeRezObject;
         public event Action<IClientAPI> OnRegionHandShakeReply;
         public event GenericCall2 OnRequestWearables;
-        public event GenericCall2 OnCompleteMovementToRegion;
+        public event GenericCall1 OnCompleteMovementToRegion;
         public event UpdateAgent OnAgentUpdate;
         public event AgentRequestSit OnAgentRequestSit;
         public event AgentSit OnAgentSit;
@@ -453,7 +453,7 @@ namespace OpenSim.Tests.Common.Mock
 
         public void CompleteMovement()
         {
-            OnCompleteMovementToRegion();
+            OnCompleteMovementToRegion(this);
         }
 
         public virtual void ActivateGesture(UUID assetId, UUID gestureId)
@@ -752,7 +752,7 @@ namespace OpenSim.Tests.Common.Mock
 
             if (OnCompleteMovementToRegion != null)
             {
-                OnCompleteMovementToRegion();
+                OnCompleteMovementToRegion(this);
             }
         }
         public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
-- 
cgit v1.1