diff --git a/OpenSim/Framework/MessageServerConfig.cs b/OpenSim/Framework/MessageServerConfig.cs index c378d2737f..7a50c91f51 100644 --- a/OpenSim/Framework/MessageServerConfig.cs +++ b/OpenSim/Framework/MessageServerConfig.cs @@ -38,6 +38,7 @@ namespace OpenSim.Framework public static bool DefaultHttpSSL = false; private ConfigurationMember configMember; public string DatabaseProvider = String.Empty; + public string DatabaseConnect = String.Empty; public string DefaultStartupMsg = String.Empty; public string GridCommsProvider = String.Empty; public string GridRecvKey = String.Empty; @@ -76,6 +77,11 @@ namespace OpenSim.Framework configMember.addConfigurationOption("grid_recv_key", ConfigurationOption.ConfigurationTypes.TYPE_STRING, "Key to expect from user server", "null", false); + + configMember.addConfigurationOption("database_connect", ConfigurationOption.ConfigurationTypes.TYPE_STRING, + "Connection String for Database", "", false); + + configMember.addConfigurationOption("database_provider", ConfigurationOption.ConfigurationTypes.TYPE_STRING, "DLL for database provider", "OpenSim.Data.MySQL.dll", false); @@ -115,6 +121,9 @@ namespace OpenSim.Framework case "database_provider": DatabaseProvider = (string) configuration_result; break; + case "database_connect": + DatabaseConnect = (string)configuration_result; + break; case "http_port": HttpPort = (uint) configuration_result; break; diff --git a/OpenSim/Framework/UserConfig.cs b/OpenSim/Framework/UserConfig.cs index 3c0bdfa410..3cb0503e0a 100644 --- a/OpenSim/Framework/UserConfig.cs +++ b/OpenSim/Framework/UserConfig.cs @@ -49,6 +49,10 @@ namespace OpenSim.Framework public bool HttpSSL = DefaultHttpSSL; public string InventoryUrl = String.Empty; + public UserConfig() + { + // weird, but UserManagerBase needs this. + } public UserConfig(string description, string filename) { configMember = diff --git a/OpenSim/Grid/MessagingServer/Main.cs b/OpenSim/Grid/MessagingServer/Main.cs index d2fa65915e..91f21010a6 100644 --- a/OpenSim/Grid/MessagingServer/Main.cs +++ b/OpenSim/Grid/MessagingServer/Main.cs @@ -31,7 +31,9 @@ using System.Reflection; using libsecondlife; using log4net; using log4net.Config; + using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Console; using OpenSim.Framework.Servers; @@ -88,6 +90,8 @@ namespace OpenSim.Grid.MessagingServer m_log.Info("[REGION]: Starting HTTP process"); m_httpServer = new BaseHttpServer(Cfg.HttpPort); + + msgsvc = new MessageService(Cfg); if (msgsvc.registerWithUserServer()) @@ -144,6 +148,24 @@ namespace OpenSim.Grid.MessagingServer } } + public override void RunCmd(string cmd, string[] cmdparams) + { + base.RunCmd(cmd, cmdparams); + + switch (cmd) + { + case "help": + m_console.Notice("clear-cache - Clears region cache. Should be done when regions change position. The region cache gets stale after a while."); + break; + case "clear-cache": + int entries = msgsvc.ClearRegionCache(); + m_console.Notice("Region cache cleared! Cleared " + entries.ToString() + " entries"); + break; + } + + + } + public override void Shutdown() { msgsvc.deregisterWithUserServer(); diff --git a/OpenSim/Grid/MessagingServer/MessageService.cs b/OpenSim/Grid/MessagingServer/MessageService.cs index e1beef123f..59fef7edfa 100644 --- a/OpenSim/Grid/MessagingServer/MessageService.cs +++ b/OpenSim/Grid/MessagingServer/MessageService.cs @@ -46,6 +46,7 @@ namespace OpenSim.Grid.MessagingServer private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private MessageServerConfig m_cfg; + private UserManager m_userManager; //A hashtable of all current presences this server knows about private Hashtable m_presences = new Hashtable(); @@ -62,11 +63,16 @@ namespace OpenSim.Grid.MessagingServer public MessageService(MessageServerConfig cfg) { m_cfg = cfg; + m_userManager = new UserManager(); + UserConfig uc = new UserConfig(); + uc.DatabaseConnect = cfg.DatabaseConnect; + uc.DatabaseProvider = cfg.DatabaseProvider; + + m_userManager._config = uc; + m_userManager.AddPlugin(cfg.DatabaseProvider, cfg.DatabaseConnect); } - #region RegionComms Methods - - #endregion + #region FriendList Methods @@ -123,11 +129,27 @@ namespace OpenSim.Grid.MessagingServer { // we need to send out online status update, but the user is already subscribed } - PresenceInformer friendlistupdater = new PresenceInformer(); - friendlistupdater.presence1 = friendpresence; - friendlistupdater.presence2 = userpresence; - WaitCallback cb = new WaitCallback(friendlistupdater.go); - ThreadPool.QueueUserWorkItem(cb); + UserAgentData p2Handle = m_userManager.GetUserAgentData(userpresence.agentData.AgentID); + if (p2Handle != null) + { + + userpresence.regionData.regionHandle = p2Handle.Handle; + PresenceInformer friendlistupdater = new PresenceInformer(); + friendlistupdater.presence1 = friendpresence; + //friendlistupdater.gridserverurl = m_cfg.GridServerURL; + //friendlistupdater.gridserversendkey = m_cfg.GridSendKey; + //friendlistupdater.gridserverrecvkey = m_cfg.GridRecvKey; + friendlistupdater.presence2 = userpresence; + friendlistupdater.OnGetRegionData += GetRegionInfo; + friendlistupdater.OnDone += PresenceUpdateDone; + WaitCallback cb = new WaitCallback(friendlistupdater.go); + ThreadPool.QueueUserWorkItem(cb); + + } + else + { + // Skip because we can't find any data on the user + } //SendRegionPresenceUpdate(friendpresence, userpresence); } @@ -143,12 +165,30 @@ namespace OpenSim.Grid.MessagingServer { // we need to send out online status update, but the user is already subscribed } - PresenceInformer friendlistupdater = new PresenceInformer(); - friendlistupdater.presence1 = userpresence; - friendlistupdater.presence2 = friendpresence; + + UserAgentData p2Handle = m_userManager.GetUserAgentData(friendpresence.agentData.AgentID); - WaitCallback cb2 = new WaitCallback(friendlistupdater.go); - ThreadPool.QueueUserWorkItem(cb2); + if (p2Handle != null) + { + + friendpresence.regionData.regionHandle = p2Handle.Handle; + PresenceInformer friendlistupdater = new PresenceInformer(); + friendlistupdater.presence1 = userpresence; + friendlistupdater.presence2 = friendpresence; + //friendlistupdater.gridserverurl = m_cfg.GridServerURL; + //friendlistupdater.gridserversendkey = m_cfg.GridSendKey; + //friendlistupdater.gridserverrecvkey = m_cfg.GridRecvKey; + friendlistupdater.OnGetRegionData += GetRegionInfo; + friendlistupdater.OnDone += PresenceUpdateDone; + WaitCallback cb2 = new WaitCallback(friendlistupdater.go); + ThreadPool.QueueUserWorkItem(cb2); + } + else + { + // skip, agent doesn't appear to exist anymore + } + + //SendRegionPresenceUpdate(userpresence, friendpresence); } @@ -209,6 +249,7 @@ namespace OpenSim.Grid.MessagingServer /// private void ProcessLogOff(LLUUID AgentID) { + m_log.Info("[LOGOFF]: Processing Logoff"); UserPresenceData AgentData = null; List AgentsNeedingNotification = new List(); UserPresenceData friendd = null; @@ -223,6 +264,7 @@ namespace OpenSim.Grid.MessagingServer if (AgentData != null) { AgentsNeedingNotification = AgentData.subscriptionData; + AgentData.OnlineYN = false; //lock (m_presence_BackReferences) //{ //if (m_presence_BackReferences.Contains(AgentID)) @@ -262,13 +304,33 @@ namespace OpenSim.Grid.MessagingServer m_presences[AgentsNeedingNotification[i]] = friendd; } - PresenceInformer friendlistupdater = new PresenceInformer(); - friendlistupdater.presence1 = AgentData; - friendlistupdater.presence2 = friendd; + UserAgentData p2Handle = m_userManager.GetUserAgentData(friendd.agentData.AgentID); + if (p2Handle != null) + { + + + friendd.regionData.regionHandle = p2Handle.Handle; + PresenceInformer friendlistupdater = new PresenceInformer(); + friendlistupdater.presence1 = AgentData; + friendlistupdater.presence2 = friendd; - WaitCallback cb3 = new WaitCallback(friendlistupdater.go); - ThreadPool.QueueUserWorkItem(cb3); + //friendlistupdater.gridserverurl = m_cfg.GridServerURL; + //friendlistupdater.gridserversendkey = m_cfg.GridSendKey; + //friendlistupdater.gridserverrecvkey = m_cfg.GridRecvKey; + friendlistupdater.OnGetRegionData += GetRegionInfo; + friendlistupdater.OnDone += PresenceUpdateDone; + + WaitCallback cb3 = new WaitCallback(friendlistupdater.go); + ThreadPool.QueueUserWorkItem(cb3); + + + + } + else + { + // skip, agent can't be found + } //SendRegionPresenceUpdate(AgentData, friendd); //removeBackReference(AgentID, AgentsNeedingNotification[i]); @@ -279,6 +341,12 @@ namespace OpenSim.Grid.MessagingServer #endregion + public void PresenceUpdateDone(PresenceInformer obj) + { + obj.OnGetRegionData -= GetRegionInfo; + obj.OnDone -= PresenceUpdateDone; + } + #region UserServer Comms /// @@ -393,7 +461,7 @@ namespace OpenSim.Grid.MessagingServer up.friendData = flData; RegionProfileData riData = GetRegionInfo(regionHandle); up.regionData = riData; - + up.OnlineYN = true; ProcessFriendListSubscriptions(up); return new XmlRpcResponse(); @@ -407,6 +475,7 @@ namespace OpenSim.Grid.MessagingServer /// public XmlRpcResponse UserLoggedOff(XmlRpcRequest request) { + m_log.Info("[USERLOGOFF]: User logged off called"); Hashtable requestData = (Hashtable)request.Params[0]; LLUUID AgentID = new LLUUID((string)requestData["agentid"]); @@ -423,23 +492,64 @@ namespace OpenSim.Grid.MessagingServer /// /// Gets and caches a RegionInfo object from the gridserver based on regionhandle /// if the regionhandle is already cached, use the cached values + /// Gets called by lots of threads!!!!! /// /// handle to the XY of the region we're looking for /// A RegionInfo object to stick in the presence info public RegionProfileData GetRegionInfo(ulong regionhandle) { RegionProfileData regionInfo = null; - if (m_regionInfoCache.Contains(regionhandle)) + bool lookup = false; + + lock (m_regionInfoCache) { - regionInfo = (RegionProfileData)m_regionInfoCache[regionhandle]; + if (m_regionInfoCache.Contains(regionhandle)) + { + regionInfo = (RegionProfileData)m_regionInfoCache[regionhandle]; + } + else + { + // Don't lock the cache while we're looking up the region! + lookup = true; + } } - else + + if (lookup) { regionInfo = RequestRegionInfo(regionhandle); + + if (regionInfo != null) + { + lock (m_regionInfoCache) + { + if (m_regionInfoCache.Contains(regionhandle)) + { + m_regionInfoCache[regionhandle] = regionInfo; + } + else + { + m_regionInfoCache.Add(regionhandle, regionInfo); + } + } + } } + return regionInfo; } + public int ClearRegionCache() + { + int cachecount = 0; + + lock (m_regionInfoCache) + { + cachecount = m_regionInfoCache.Count; + m_regionInfoCache.Clear(); + } + + return cachecount; + } + /// /// Get RegionProfileData from the GridServer /// We'll Cache this information and use it for presence updates @@ -541,6 +651,7 @@ namespace OpenSim.Grid.MessagingServer // Process Response if (GridRespData.ContainsKey("responsestring")) { + return true; } else diff --git a/OpenSim/Grid/MessagingServer/PresenceInformer.cs b/OpenSim/Grid/MessagingServer/PresenceInformer.cs index 59d0e130cf..050d88a951 100644 --- a/OpenSim/Grid/MessagingServer/PresenceInformer.cs +++ b/OpenSim/Grid/MessagingServer/PresenceInformer.cs @@ -27,16 +27,31 @@ using System.Collections; using System.Reflection; +using System.Net; using log4net; using Nwc.XmlRpc; using OpenSim.Data; namespace OpenSim.Grid.MessagingServer { + public delegate RegionProfileData GetRegionData(ulong region_handle); + public delegate void Done(PresenceInformer obj); + + public class PresenceInformer { + public event GetRegionData OnGetRegionData; + public event Done OnDone; + + private GetRegionData handlerGetRegionData = null; + private Done handlerDone = null; + public UserPresenceData presence1 = null; public UserPresenceData presence2 = null; + public string gridserverurl, gridserversendkey, gridserverrecvkey; + public bool lookupRegion = true; + //public methodGroup + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public PresenceInformer() @@ -60,18 +75,68 @@ namespace OpenSim.Grid.MessagingServer public void SendRegionPresenceUpdate(UserPresenceData TalkingAbout, UserPresenceData UserToUpdate) { // TODO: Fill in pertenant Presence Data from 'TalkingAbout' + RegionProfileData whichRegion = new RegionProfileData(); + if (lookupRegion) + { + handlerGetRegionData = OnGetRegionData; + if (handlerGetRegionData != null) + { + whichRegion = handlerGetRegionData(UserToUpdate.regionData.regionHandle); + } + //RegionProfileData rp = RegionProfileData.RequestSimProfileData(UserToUpdate.regionData.regionHandle, gridserverurl, gridserversendkey, gridserverrecvkey); - RegionProfileData whichRegion = UserToUpdate.regionData; + //whichRegion = rp; + } + else + { + whichRegion = UserToUpdate.regionData; + } //whichRegion.httpServerURI - Hashtable PresenceParams = new Hashtable(); - ArrayList SendParams = new ArrayList(); - SendParams.Add(PresenceParams); + if (whichRegion != null) + { + + + Hashtable PresenceParams = new Hashtable(); + PresenceParams.Add("agent_id",TalkingAbout.agentData.AgentID.ToString()); + PresenceParams.Add("notify_id",UserToUpdate.agentData.AgentID.ToString()); + if (TalkingAbout.OnlineYN) + PresenceParams.Add("status","TRUE"); + else + PresenceParams.Add("status","FALSE"); + + + + + ArrayList SendParams = new ArrayList(); + SendParams.Add(PresenceParams); + + + m_log.Info("[PRESENCE]: Informing " + whichRegion.regionName + " at " + whichRegion.httpServerURI); + // Send + XmlRpcRequest RegionReq = new XmlRpcRequest("presence_update", SendParams); + try + { + + XmlRpcResponse RegionResp = RegionReq.Send(whichRegion.httpServerURI, 6000); + } + catch (WebException) + { + m_log.WarnFormat("[INFORM]: failed notifying region {0} containing user {1} about {2}", whichRegion.regionName, UserToUpdate.agentData.firstname + " " + UserToUpdate.agentData.lastname, TalkingAbout.agentData.firstname + " " + TalkingAbout.agentData.lastname); + } + } + else + { + m_log.Info("[PRESENCEUPDATER]: Region data was null skipping"); + + } + + handlerDone = OnDone; + if (handlerDone != null) + { + handlerDone(this); + } - m_log.Info("[PRESENCE]: Informing " + whichRegion.regionName + " at " + whichRegion.httpServerURI); - // Send - XmlRpcRequest RegionReq = new XmlRpcRequest("presence_update", SendParams); - XmlRpcResponse RegionResp = RegionReq.Send(whichRegion.httpServerURI, 6000); } } } diff --git a/OpenSim/Grid/MessagingServer/UserPresenceData.cs b/OpenSim/Grid/MessagingServer/UserPresenceData.cs index 71882011fa..74a6032101 100644 --- a/OpenSim/Grid/MessagingServer/UserPresenceData.cs +++ b/OpenSim/Grid/MessagingServer/UserPresenceData.cs @@ -40,6 +40,7 @@ namespace OpenSim.Grid.MessagingServer public string httpURI = String.Empty; public List friendData = new List (); public List subscriptionData = new List(); + public bool OnlineYN = false; public UserPresenceData() { diff --git a/OpenSim/Grid/UserServer/MessageServersConnector.cs b/OpenSim/Grid/UserServer/MessageServersConnector.cs index 529c089779..208131eedf 100644 --- a/OpenSim/Grid/UserServer/MessageServersConnector.cs +++ b/OpenSim/Grid/UserServer/MessageServersConnector.cs @@ -185,12 +185,12 @@ namespace OpenSim.Grid.UserServer { if (MessageServers.Count > 0) { - m_log.Info("[MSGCONNECTOR]: Sending login notice to registered message servers"); + m_log.Info("[MSGCONNECTOR]: Sending logoff notice to registered message servers"); } else -// { + { // m_log.Debug("[MSGCONNECTOR]: No Message Servers registered, ignoring"); -// } + } foreach (MessageServerInfo serv in MessageServers.Values) { NotifyMessageServerAboutUserLogoff(serv,agentID); diff --git a/OpenSim/Region/Communications/OGS1/OGS1GridServices.cs b/OpenSim/Region/Communications/OGS1/OGS1GridServices.cs index 2e892c2319..0daabc577c 100644 --- a/OpenSim/Region/Communications/OGS1/OGS1GridServices.cs +++ b/OpenSim/Region/Communications/OGS1/OGS1GridServices.cs @@ -382,7 +382,13 @@ namespace OpenSim.Region.Communications.OGS1 regionInfo.RegionID = new LLUUID((string) responseData["region_UUID"]); regionInfo.RegionName = (string) responseData["region_name"]; - m_remoteRegionInfoCache.Add(regionHandle, regionInfo); + lock (m_remoteRegionInfoCache) + { + if (!m_remoteRegionInfoCache.ContainsKey(regionHandle)) + { + m_remoteRegionInfoCache.Add(regionHandle, regionInfo); + } + } } catch (WebException) { diff --git a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs index c82f88dc18..92c808bb18 100644 --- a/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/Friends/FriendsModule.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; +using System.Collections; using System.Collections.Generic; using System.Reflection; using libsecondlife; @@ -45,6 +46,8 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends private Dictionary> FriendLists = new Dictionary>(); private Dictionary m_pendingFriendRequests = new Dictionary(); private Dictionary m_rootAgents = new Dictionary(); + private Dictionary> StoredFriendListUpdates = new Dictionary>(); + private List m_scene = new List(); #region IRegionModule Members @@ -91,6 +94,73 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends public XmlRpcResponse processPresenceUpdate(XmlRpcRequest req) { m_log.Info("[FRIENDS]: Got Notification about a user! OMG"); + Hashtable requestData = (Hashtable)req.Params[0]; + if (requestData.ContainsKey("agent_id") && requestData.ContainsKey("notify_id") && requestData.ContainsKey("status")) + { + LLUUID notifyAgentId = LLUUID.Zero; + LLUUID notifyAboutAgentId = LLUUID.Zero; + bool notifyOnlineStatus = false; + + if ((string)requestData["status"] == "TRUE") + notifyOnlineStatus = true; + + Helpers.TryParse((string)requestData["notify_id"], out notifyAgentId); + + Helpers.TryParse((string)requestData["agent_id"], out notifyAboutAgentId); + + ScenePresence avatar = GetPresenceFromAgentID(notifyAgentId); + if (avatar != null) + { + if (avatar.IsChildAgent) + { + StoredFriendListUpdate sob = new StoredFriendListUpdate(); + sob.OnlineYN = notifyOnlineStatus; + sob.storedAbout = notifyAboutAgentId; + sob.storedFor = notifyAgentId; + lock (StoredFriendListUpdates) + { + if (StoredFriendListUpdates.ContainsKey(notifyAgentId)) + { + StoredFriendListUpdates[notifyAgentId].Add(sob); + } + else + { + List newitem = new List(); + newitem.Add(sob); + StoredFriendListUpdates.Add(notifyAgentId, newitem); + } + } + } + else + { + if (notifyOnlineStatus) + doFriendListUpdateOnline(notifyAboutAgentId); + else + ClientLoggedOut(notifyAboutAgentId); + } + } + else + { + StoredFriendListUpdate sob = new StoredFriendListUpdate(); + sob.OnlineYN = notifyOnlineStatus; + sob.storedAbout = notifyAboutAgentId; + sob.storedFor = notifyAgentId; + lock (StoredFriendListUpdates) + { + if (StoredFriendListUpdates.ContainsKey(notifyAgentId)) + { + StoredFriendListUpdates[notifyAgentId].Add(sob); + } + else + { + List newitem = new List(); + newitem.Add(sob); + StoredFriendListUpdates.Add(notifyAgentId, newitem); + } + } + } + + } return new XmlRpcResponse(); } @@ -110,24 +180,30 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends client.OnDenyFriendRequest += OnDenyFriendRequest; client.OnTerminateFriendship += OnTerminateFriendship; + doFriendListUpdateOnline(client.AgentId); + + } + + private void doFriendListUpdateOnline(LLUUID AgentId) + { List fl = new List(); //bool addFLback = false; lock (FriendLists) { - if (FriendLists.ContainsKey(client.AgentId)) + if (FriendLists.ContainsKey(AgentId)) { - fl = FriendLists[client.AgentId]; + fl = FriendLists[AgentId]; } else { - fl = m_scene[0].GetFriendList(client.AgentId); + fl = m_scene[0].GetFriendList(AgentId); //lock (FriendLists) //{ - if (!FriendLists.ContainsKey(client.AgentId)) - FriendLists.Add(client.AgentId, fl); + if (!FriendLists.ContainsKey(AgentId)) + FriendLists.Add(AgentId, fl); //} } } @@ -161,11 +237,11 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends { foreach (FriendListItem fli in usrfl) { - if (fli.Friend == client.AgentId) + if (fli.Friend == AgentId) { fli.onlinestatus = true; LLUUID[] Agents = new LLUUID[1]; - Agents[0] = client.AgentId; + Agents[0] = AgentId; av.ControllingClient.SendAgentOnline(Agents); } @@ -176,8 +252,11 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends if (UpdateUsers.Count > 0) { - - client.SendAgentOnline(UpdateUsers.ToArray()); + ScenePresence avatar = GetPresenceFromAgentID(AgentId); + if (avatar != null) + { + avatar.ControllingClient.SendAgentOnline(UpdateUsers.ToArray()); + } } } @@ -302,6 +381,27 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends { m_rootAgents.Add(avatar.UUID, avatar.RegionHandle); m_log.Info("[FRIEND]: Claiming " + avatar.Firstname + " " + avatar.Lastname + " in region:" + avatar.RegionHandle + "."); + + List updateme = new List(); + lock (StoredFriendListUpdates) + { + if (StoredFriendListUpdates.ContainsKey(avatar.UUID)) + { + updateme = StoredFriendListUpdates[avatar.UUID]; + StoredFriendListUpdates.Remove(avatar.UUID); + } + } + + if (updateme.Count > 0) + { + foreach (StoredFriendListUpdate u in updateme) + { + if (u.OnlineYN) + doFriendListUpdateOnline(u.storedAbout); + else + ClientLoggedOut(u.storedAbout); + } + } } } //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString()); @@ -441,8 +541,13 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends SceneAgentIn.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); SceneAgentIn.StoreAddFriendship(m_pendingFriendRequests[transactionID], agentID, (uint) 1); - m_pendingFriendRequests.Remove(transactionID); + + //LLUUID[] Agents = new LLUUID[1]; + //Agents[0] = msg.toAgentID; + //av.ControllingClient.SendAgentOnline(Agents); + + m_pendingFriendRequests.Remove(transactionID); // TODO: Inform agent that the friend is online } } @@ -498,4 +603,11 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends #endregion } + + public struct StoredFriendListUpdate + { + public LLUUID storedFor; + public LLUUID storedAbout; + public bool OnlineYN; + } }