29 using System.Collections;
30 using System.Collections.Generic;
32 using System.Reflection;
33 using System.Threading;
39 using OpenSim.Framework;
40 using OpenSim.Framework.Servers.HttpServer;
41 using OpenSim.Framework.Servers;
42 using OpenSim.Region.Framework.Interfaces;
43 using OpenSim.Region.Framework.Scenes;
44 using OpenSim.Services.Interfaces;
45 using OpenSim.Services.Connectors.Friends;
46 using OpenSim.Server.Base;
53 [Extension(Path =
"/OpenSim/RegionModules", NodeName =
"RegionModule", Id =
"FriendsModule")]
56 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
58 protected bool m_Enabled =
false;
80 protected List<Scene> m_Scenes =
new List<Scene>();
93 protected Dictionary<UUID, UserFriendData> m_Friends =
new Dictionary<UUID, UserFriendData>();
99 protected HashSet<UUID> m_NeedsToNotifyStatus =
new HashSet<UUID>();
105 protected HashSet<UUID> m_NeedsListOfOnlineFriends =
new HashSet<UUID>();
111 if (m_PresenceService == null)
113 if (m_Scenes.Count > 0)
117 return m_PresenceService;
125 if (m_FriendsService == null)
127 if (m_Scenes.Count > 0)
128 m_FriendsService = m_Scenes[0].RequestModuleInterface<
IFriendsService>();
131 return m_FriendsService;
137 get {
return m_Scenes[0].GridService; }
142 get {
return m_Scenes[0].UserAccountService; }
149 if (m_Scenes.Count > 0)
156 #region ISharedRegionModule
159 IConfig moduleConfig = config.Configs[
"Modules"];
160 if (moduleConfig != null)
162 string name = moduleConfig.GetString(
"FriendsModule",
"FriendsModule");
168 m_log.DebugFormat(
"[FRIENDS MODULE]: {0} enabled.", Name);
175 IConfig friendsConfig = config.Configs[
"Friends"];
176 if (friendsConfig != null)
178 int mPort = friendsConfig.GetInt(
"Port", 0);
180 string connector = friendsConfig.GetString(
"Connector", String.Empty);
183 m_FriendsService = ServerUtils.LoadPlugin<
IFriendsService>(connector, args);
187 IHttpServer server = MainServer.GetHttpServer((uint)mPort);
193 if (m_FriendsService == null)
195 m_log.Error(
"[FRIENDS]: No Connector defined in section Friends, or failed to load, cannot continue");
196 throw new Exception(
"Connector load error");
218 scene.EventManager.OnNewClient += OnNewClient;
219 scene.EventManager.OnClientClosed += OnClientClosed;
220 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
221 scene.EventManager.OnClientLogin += OnClientLogin;
231 m_Scenes.Remove(scene);
234 public virtual string Name
236 get {
return "FriendsModule"; }
239 public Type ReplaceableInterface
248 FriendInfo[] friends = GetFriendsFromCache(principalID);
249 FriendInfo finfo = GetFriend(friends, friendID);
252 return finfo.TheirFlags;
260 client.OnInstantMessage += OnInstantMessage;
261 client.OnApproveFriendRequest += OnApproveFriendRequest;
262 client.OnDenyFriendRequest += OnDenyFriendRequest;
263 client.OnTerminateFriendship += RemoveFriendship;
264 client.OnGrantUserRights += GrantRights;
265 client.OnFindAgent += FindFriend;
274 CacheFriends(client);
287 UUID agentID = client.AgentId;
291 if (m_Friends.TryGetValue(agentID, out friendsData))
293 friendsData.Refcount++;
299 friendsData.PrincipalID = agentID;
300 friendsData.Friends = GetFriendsFromService(client);
301 friendsData.Refcount = 1;
303 m_Friends[agentID] = friendsData;
309 private void OnClientClosed(UUID agentID,
Scene scene)
320 UserFriendData friendsData;
321 if (m_Friends.TryGetValue(agentID, out friendsData))
323 friendsData.Refcount--;
324 if (friendsData.Refcount <= 0)
325 m_Friends.Remove(agentID);
334 lock (m_NeedsToNotifyStatus)
336 if (m_NeedsToNotifyStatus.Remove(sp.
UUID))
346 UUID agentID = client.AgentId;
354 lock (m_NeedsToNotifyStatus)
355 m_NeedsToNotifyStatus.Add(agentID);
358 lock (m_NeedsListOfOnlineFriends)
359 m_NeedsListOfOnlineFriends.Add(agentID);
362 public virtual
bool SendFriendsOnlineIfNeeded(
IClientAPI client)
364 UUID agentID = client.AgentId;
367 lock (m_NeedsListOfOnlineFriends)
369 if (!m_NeedsListOfOnlineFriends.Remove(agentID))
374 List<UUID> online = GetOnlineFriends(agentID);
376 if (online.Count > 0)
377 client.SendAgentOnline(online.ToArray());
380 List<string> outstanding =
new List<string>();
381 FriendInfo[] friends = GetFriendsFromCache(agentID);
385 outstanding.Add(fi.Friend);
389 "Will you be my friend?",
true, Vector3.Zero);
391 foreach (
string fid
in outstanding)
394 string firstname =
"Unknown", lastname =
"UserFMSFOIN";
397 m_log.DebugFormat(
"[FRIENDS MODULE]: skipping malformed friend {0}", fid);
402 im.fromAgentID = fromAgentID.Guid;
403 im.fromAgentName = firstname +
" " + lastname;
404 im.imSessionID = im.fromAgentID;
405 im.message = FriendshipMessage(fid);
407 LocalFriendshipOffered(agentID, im);
415 return "Will you be my friend?";
418 protected virtual bool GetAgentInfo(UUID scopeID,
string fid, out UUID agentID, out
string first, out
string last)
420 first =
"Unknown"; last =
"UserFMGAI";
421 if (!
UUID.TryParse(fid, out agentID))
424 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(scopeID, agentID);
427 first = account.FirstName;
428 last = account.LastName;
434 List<UUID> GetOnlineFriends(UUID userID)
436 List<string> friendList =
new List<string>();
438 FriendInfo[] friends = GetFriendsFromCache(userID);
442 friendList.Add(fi.Friend);
445 List<UUID> online =
new List<UUID>();
447 if (friendList.Count > 0)
448 GetOnlineFriends(userID, friendList, online);
456 protected virtual void GetOnlineFriends(UUID userID, List<string> friendList, List<UUID> online)
461 PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
466 online.Add(presenceID);
477 foreach (
Scene scene
in m_Scenes)
481 return presence.ControllingClient;
495 FriendInfo[] friends = GetFriendsFromCache(agentID);
496 if (friends.Length > 0)
498 List<FriendInfo> friendList =
new List<FriendInfo>();
501 if (((fi.
MyFlags & (
int)FriendRights.CanSeeOnline) != 0) && (fi.TheirFlags != -1))
513 StatusNotify(friendList, agentID, online);
514 }, null,
"FriendsModule.StatusChange"
519 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID,
bool online)
523 List<string> friendStringIds = friendList.ConvertAll<
string>(
friend => friend.Friend);
524 List<string> remoteFriendStringIds =
new List<string>();
525 foreach (
string friendStringId
in friendStringIds)
528 if (
UUID.TryParse(friendStringId, out friendUuid))
530 if (LocalStatusNotification(userID, friendUuid, online))
533 remoteFriendStringIds.Add(friendStringId);
537 m_log.WarnFormat(
"[FRIENDS]: Error parsing friend ID {0}", friendStringId);
543 PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray());
548 if (friendSession != null && friendSession.
RegionID !=
UUID.Zero)
551 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
554 m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online);
564 if ((InstantMessageDialog)im.
dialog == InstantMessageDialog.FriendshipOffered)
570 m_log.DebugFormat(
"[FRIENDS]: {0} ({1}) offered friendship to {2} ({3})", principalID, client.FirstName + client.LastName, friendID, im.fromAgentName);
573 FriendInfo[] finfos = GetFriendsFromCache(principalID);
579 client.SendAgentAlertMessage(
"This person is already your friend. Please delete it first if you want to reestablish the friendship.",
false);
586 StoreBackwards(friendID, principalID);
589 ForwardFriendshipOffer(principalID, friendID, im);
597 im.imSessionID = im.fromAgentID;
598 im.fromAgentName = GetFriendshipRequesterName(agentID);
601 if (LocalFriendshipOffered(friendID, im))
605 PresenceInfo[] friendSessions = PresenceService.GetAgents(
new string[] { friendID.ToString() });
606 if (friendSessions != null && friendSessions.Length > 0)
609 if (friendSession != null)
611 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
612 m_FriendsSimConnector.FriendshipOffered(region, agentID, friendID, im.message);
622 UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID);
623 return (account == null) ?
"Unknown" : account.FirstName +
" " + account.LastName;
628 m_log.DebugFormat(
"[FRIENDS]: {0} accepted friendship from {1}", client.AgentId, friendID);
630 AddFriendship(client, friendID);
635 StoreFriendships(client.
AgentId, friendID);
640 ccm.CreateCallingCard(client.AgentId, friendID, UUID.Zero);
644 RecacheFriends(client);
651 if (LocalFriendshipApproved(client.
AgentId, client.
Name, friendID))
653 client.SendAgentOnline(
new UUID[] { friendID });
658 PresenceInfo[] friendSessions = PresenceService.GetAgents(
new string[] { friendID.ToString() });
659 if (friendSessions != null && friendSessions.Length > 0)
662 if (friendSession != null)
664 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
665 m_FriendsSimConnector.FriendshipApproved(region, client.AgentId, client.Name, friendID);
666 client.SendAgentOnline(
new UUID[] { friendID });
671 private void OnDenyFriendRequest(
IClientAPI client,
UUID friendID, List<UUID> callingCardFolders)
673 m_log.DebugFormat(
"[FRIENDS]: {0} denied friendship to {1}", client.AgentId, friendID);
675 DeleteFriendship(client.
AgentId, friendID);
682 if (LocalFriendshipDenied(client.
AgentId, client.
Name, friendID))
685 PresenceInfo[] friendSessions = PresenceService.GetAgents(
new string[] { friendID.ToString() });
686 if (friendSessions != null && friendSessions.Length > 0)
689 if (friendSession != null)
691 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
693 m_FriendsSimConnector.FriendshipDenied(region, client.AgentId, client.Name, friendID);
695 m_log.WarnFormat(
"[FRIENDS]: Could not find region {0} in locating {1}", friendSession.RegionID, friendID);
702 if (!DeleteFriendship(client.
AgentId, exfriendID))
703 client.SendAlertMessage(
"Unable to terminate friendship on this sim.");
706 RecacheFriends(client);
708 client.SendTerminateFriend(exfriendID);
715 if (LocalFriendshipTerminated(client.
AgentId, exfriendID))
718 PresenceInfo[] friendSessions = PresenceService.GetAgents(
new string[] { exfriendID.ToString() });
719 if (friendSessions != null && friendSessions.Length > 0)
722 if (friendSession != null)
724 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
725 m_FriendsSimConnector.FriendshipTerminated(region, client.AgentId, exfriendID);
732 UUID requester = remoteClient.AgentId;
733 if(requester != HunterID)
736 FriendInfo[] friends = GetFriendsFromCache(requester);
737 if (friends.Length == 0)
740 FriendInfo friend = GetFriend(friends, PreyID);
744 if((
friend.TheirFlags & (
int)FriendRights.CanSeeOnMap) == 0)
749 if(hunterScene == null)
760 px = hunterScene.RegionInfo.WorldLocX + sp.AbsolutePosition.X;
761 py = hunterScene.RegionInfo.WorldLocY + sp.AbsolutePosition.Y;
763 remoteClient.SendFindAgent(HunterID, PreyID, px, py);
767 PresenceInfo[] friendSessions = PresenceService.GetAgents(
new string[] { PreyID.ToString() });
769 if (friendSessions == null || friendSessions.Length == 0)
773 if (friendSession == null)
776 GridRegion region = GridService.GetRegionByUUID(hunterScene.RegionInfo.ScopeID, friendSession.RegionID);
782 px = region.RegionLocX + 128.0;
783 py = region.RegionLocY + 128.0;
785 remoteClient.SendFindAgent(HunterID, PreyID, px, py);
790 UUID requester = remoteClient.AgentId;
793 "[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}",
794 requester, rights, friendID);
796 FriendInfo[] friends = GetFriendsFromCache(requester);
797 if (friends.Length == 0)
803 FriendInfo friend = GetFriend(friends, friendID);
808 if (!StoreRights(requester, friendID, rights))
810 remoteClient.SendAlertMessage(
"Unable to grant rights.");
815 int myFlags = friend.MyFlags;
816 friend.MyFlags = rights;
819 remoteClient.SendChangeUserRights(requester, friendID, rights);
826 if (LocalGrantRights(requester, friendID, myFlags, rights))
829 PresenceInfo[] friendSessions = PresenceService.GetAgents(
new string[] { friendID.ToString() });
830 if (friendSessions != null && friendSessions.Length > 0)
833 if (friendSession != null)
835 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
838 m_FriendsSimConnector.GrantRights(region, requester, friendID, myFlags, rights);
844 m_log.DebugFormat(
"[FRIENDS MODULE]: friend {0} not found for {1}", friendID, requester);
852 if (fi.
Friend == friendID.ToString())
862 IClientAPI friendClient = LocateClientObject(toID);
863 if (friendClient != null)
866 friendClient.SendInstantMessage(im);
875 IClientAPI friendClient = LocateClientObject(friendID);
876 if (friendClient != null)
880 (byte)OpenMetaverse.InstantMessageDialog.FriendshipAccepted, userID.ToString(),
false, Vector3.Zero);
881 friendClient.SendInstantMessage(im);
886 ccm.CreateCallingCard(friendID, userID, UUID.Zero);
890 RecacheFriends(friendClient);
901 IClientAPI friendClient = LocateClientObject(friendID);
902 if (friendClient != null)
906 (byte)OpenMetaverse.InstantMessageDialog.FriendshipDeclined, userID.ToString(),
false, Vector3.Zero);
907 friendClient.SendInstantMessage(im);
917 IClientAPI friendClient = LocateClientObject(exfriendID);
918 if (friendClient != null)
921 friendClient.SendTerminateFriend(userID);
923 RecacheFriends(friendClient);
933 IClientAPI friendClient = LocateClientObject(friendID);
934 if (friendClient != null)
936 int changedRights = newRights ^ oldRights;
937 bool onlineBitChanged = (changedRights & (int)FriendRights.CanSeeOnline) != 0;
938 if (onlineBitChanged)
940 if ((newRights & (
int)FriendRights.CanSeeOnline) == 1)
941 friendClient.SendAgentOnline(
new UUID[] { userID });
943 friendClient.SendAgentOffline(
new UUID[] { userID });
946 if(changedRights != 0)
947 friendClient.SendChangeUserRights(userID, friendID, newRights);
950 UpdateLocalCache(userID, friendID, newRights);
962 IClientAPI friendClient = LocateClientObject(friendID);
963 if (friendClient != null)
967 friendClient.SendAgentOnline(
new UUID[] { userID });
969 friendClient.SendAgentOffline(
new UUID[] { userID });
979 #region Get / Set friends in several flavours
987 if (m_Friends.TryGetValue(userID, out friendsData))
991 return EMPTY_FRIENDS;
1005 FriendInfo[] friends = GetFriendsFromCache(friendID);
1006 if(friends != EMPTY_FRIENDS)
1008 FriendInfo finfo = GetFriend(friends, userID);
1010 finfo.TheirFlags = rights;
1017 return FriendsService.GetFriends(client.AgentId);
1024 UUID agentID = client.AgentId;
1028 if (m_Friends.TryGetValue(agentID, out friendsData))
1029 friendsData.
Friends = GetFriendsFromService(client);
1036 return m_Friends.ContainsKey(userID);
1039 protected virtual bool StoreRights(UUID agentID, UUID friendID,
int rights)
1041 FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), rights);
1047 FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
1052 FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), (int)FriendRights.CanSeeOnline);
1053 FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), (int)FriendRights.CanSeeOnline);
1058 FriendsService.Delete(agentID, exfriendID.ToString());
1059 FriendsService.Delete(exfriendID, agentID.ToString());
virtual bool CacheFriends(IClientAPI client)
Cache the friends list or increment the refcount for the existing friends list.
virtual void OnInstantMessage(IClientAPI client, GridInstantMessage im)
IClientAPI ControllingClient
virtual string FriendshipMessage(string friendID)
void RecacheFriends(IClientAPI client)
virtual void OnApproveFriendRequest(IClientAPI client, UUID friendID, List< UUID > callingCardFolders)
virtual void StatusNotify(List< FriendInfo > friendList, UUID userID, bool online)
bool IsFriend(string friend)
void UpdateLocalCache(UUID userID, UUID friendID, int rights)
Update local cache only
int MyFlags
The permissions that this user has granted to the friend.
virtual void GetOnlineFriends(UUID userID, List< string > friendList, List< UUID > online)
virtual void InitModule(IConfigSource config)
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
virtual FriendInfo[] GetFriendsFromService(IClientAPI client)
void FindFriend(IClientAPI remoteClient, UUID HunterID, UUID PreyID)
bool AreFriendsCached(UUID userID)
Are friends cached on this simulator for a particular user?
void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
void RemoveFriendship(IClientAPI client, UUID exfriendID)
Remove a friendship between two users.
string Name
Returns the full name of the agent/avatar represented by this client
bool LocalGrantRights(UUID userID, UUID friendID, int oldRights, int newRights)
void AddFriendship(IClientAPI client, UUID friendID)
Add a friendship between two users.
virtual void StoreBackwards(UUID friendID, UUID agentID)
virtual void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
bool LocalFriendshipDenied(UUID userID, string userName, UUID friendID)
virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
Interface to OpenSimulator's built in HTTP server. Use this to register handlers (http, llsd, xmlrpc, etc.) for given URLs.
FriendsSimConnector m_FriendsSimConnector
void PostInitialise()
This is called exactly once after all the shared region-modules have been instanciated and IRegionMod...
virtual int GetRightsGrantedByFriend(UUID principalID, UUID friendID)
Get permissions granted by a friend.
FriendInfo[] GetFriendsFromCache(UUID userID)
Get friends from local cache only
void GrantRights(IClientAPI remoteClient, UUID friendID, int rights)
Grant permissions for a friend.
delegate void StatusChange(bool status)
OpenSim.Services.Interfaces.PresenceInfo PresenceInfo
bool LocalFriendshipTerminated(UUID userID, UUID exfriendID)
virtual bool StoreRights(UUID agentID, UUID friendID, int rights)
bool LocalFriendshipApproved(UUID userID, string userName, UUID friendID)
override bool TryGetScenePresence(UUID agentID, out ScenePresence sp)
Try to get a scene presence from the scene
IClientAPI LocateClientObject(UUID agentID)
Find the client for a ID
virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
virtual bool DeleteFriendship(UUID agentID, UUID exfriendID)
bool LocalStatusNotification(UUID userID, UUID friendID, bool online)
int TheirFlags
The permissions that the friend has granted to this user.
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
virtual string GetFriendshipRequesterName(UUID agentID)
virtual bool ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im)
OpenSim.Services.Interfaces.GridRegion GridRegion
virtual void StoreFriendships(UUID agentID, UUID friendID)
virtual void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
virtual bool LocalFriendshipOffered(UUID toID, GridInstantMessage im)
OpenSim.Services.Interfaces.FriendInfo FriendInfo