try improve profiles online indication a bit more

This commit is contained in:
UbitUmarov
2023-02-01 18:56:08 +00:00
parent a9cc7594e2
commit b327224b74
4 changed files with 97 additions and 34 deletions

View File

@@ -88,6 +88,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
/// </remarks>
protected Dictionary<UUID, UserFriendData> m_Friends = new();
protected Dictionary<UUID, HashSet<UUID>> m_OnlineFriendsCache = new();
/// <summary>
/// Maintain a record of clients that need to notify about their online status. This only
/// needs to be done on login. Subsequent online/offline friend changes are sent by a different mechanism.
@@ -241,15 +243,54 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
public virtual int GetRightsGrantedByFriend(UUID principalID, UUID friendID)
{
FriendInfo[] friends = GetFriendsFromCache(principalID);
FriendInfo finfo = GetFriend(friends, friendID);
if (finfo is not null && finfo.TheirFlags != -1)
if (friends.Length > 0)
{
return finfo.TheirFlags;
FriendInfo finfo = GetFriend(friends, friendID);
if (finfo is not null && finfo.TheirFlags != -1)
{
return finfo.TheirFlags;
}
}
return 0;
}
private void OnMakeRootAgent(ScenePresence sp)
public bool IsFriendOnline(UUID userID, UUID friendID)
{
if(m_OnlineFriendsCache.TryGetValue(userID, out HashSet<UUID> friends))
return friends.Contains(friendID);
return false;
}
public void CacheFriendsOnline(UUID userID, List<UUID> friendsOnline, bool online)
{
if (!m_OnlineFriendsCache.TryGetValue(userID, out HashSet<UUID> friends))
{
friends = new HashSet<UUID>();
m_OnlineFriendsCache[userID] = friends;
}
foreach (UUID friendID in friendsOnline)
{
if (online)
friends.Add(friendID);
else
friends.Remove(friendID);
}
}
public void CacheFriendOnline(UUID userID, UUID friendID, bool online)
{
if (!m_OnlineFriendsCache.TryGetValue(userID, out HashSet<UUID> friends))
{
friends = new HashSet<UUID>();
m_OnlineFriendsCache[userID] = friends;
}
if (online)
friends.Add(friendID);
else
friends.Remove(friendID);
}
private void OnMakeRootAgent(ScenePresence sp)
{
if(sp.m_gotCrossUpdate)
return;
@@ -333,6 +374,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
lock (m_Friends)
{
m_OnlineFriendsCache.Remove(agentID);
if (m_Friends.TryGetValue(agentID, out UserFriendData friendsData))
{
friendsData.Refcount--;
@@ -438,17 +480,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
List<UUID> GetOnlineFriends(UUID userID)
{
List<string> friendList = new();
List<UUID> online = new();
FriendInfo[] friends = GetFriendsFromCache(userID);
if(friends.Length == 0)
return online;
List<string> friendList = new(friends.Length);
foreach (FriendInfo fi in friends)
{
if (((fi.TheirFlags & (int)FriendRights.CanSeeOnline) != 0) && (fi.TheirFlags != -1))
friendList.Add(fi.Friend);
}
List<UUID> online = new();
if (friendList.Count > 0)
GetOnlineFriends(userID, friendList, online);
@@ -458,16 +501,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
return online;
}
protected virtual void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
protected virtual void GetOnlineFriends(UUID userID, List<string> friendList, List<UUID> online)
{
//m_log.DebugFormat(
// "[FRIENDS MODULE]: Looking for online presence of {0} users for {1}", friendList.Count, userID);
PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
if(presence.Length == 0)
return;
if (!m_OnlineFriendsCache.TryGetValue(userID, out HashSet<UUID> friends))
{
friends = new HashSet<UUID>();
m_OnlineFriendsCache[userID] = friends;
}
foreach (PresenceInfo pi in presence)
{
if (UUID.TryParse(pi.UserID, out UUID presenceID))
{
online.Add(presenceID);
friends.Add(presenceID);
}
}
}
@@ -962,6 +1017,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
IClientAPI friendClient = LocateClientObject(friendID);
if (friendClient is not null)
{
CacheFriendOnline(friendID, userID, online);
// the friend in this sim as root agent
if (online)
friendClient.SendAgentOnline(new UUID[] { userID });
@@ -1001,7 +1057,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
lock (m_Friends)
{
FriendInfo[] friends = GetFriendsFromCache(friendID);
if(friends != EMPTY_FRIENDS)
if(friends.Length > 0)
{
FriendInfo finfo = GetFriend(friends, userID);
if(finfo is not null)
@@ -1019,11 +1075,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
{
// 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))
if (m_Friends.TryGetValue(client.AgentId, out UserFriendData friendsData))
friendsData.Friends = GetFriendsFromService(client);
}
}

View File

@@ -28,6 +28,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
public void Notify(UUID userID, Dictionary<string, List<FriendInfo>> friendsPerDomain, bool online)
{
if(m_FriendsModule is null)
return;
foreach (KeyValuePair<string, List<FriendInfo>> kvp in friendsPerDomain)
{
// For the others, call the user agent service
@@ -51,10 +54,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
List<UUID> friendsOnline = fConn.StatusNotification(ids, userID, online);
if (online && friendsOnline.Count > 0)
if (friendsOnline.Count > 0)
{
IClientAPI client = m_FriendsModule.LocateClientObject(userID);
client?.SendAgentOnline(friendsOnline.ToArray());
if(client is not null)
{
m_FriendsModule.CacheFriendsOnline(userID, friendsOnline, online);
if(online)
client?.SendAgentOnline(friendsOnline.ToArray());
else
client?.SendAgentOffline(friendsOnline.ToArray());
}
}
}
}

View File

@@ -155,7 +155,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
m_profilesCache.AddOrUpdate(props.UserId, uce, PROFILECACHEEXPIRE);
}
if (IsFriendOnline(req.client.AgentId, req.agent))
if (IsFriendOnline(req.client, req.agent))
flags |= (uint)ProfileFlags.Online;
else
flags &= (uint)~ProfileFlags.Online;
@@ -1086,9 +1086,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
{
//m_log.DebugFormat("[PROFILES]: Start PickInfoUpdate Name: {0} PickId: {1} SnapshotId: {2}", name, pickID.ToString(), snapshotID.ToString());
UserProfilePick pick = new UserProfilePick();
string serverURI = string.Empty;
GetUserProfileServerURI(remoteClient.AgentId, out serverURI);
UserProfilePick pick = new();
GetUserProfileServerURI(remoteClient.AgentId, out string serverURI);
if(string.IsNullOrWhiteSpace(serverURI))
return;
@@ -1192,10 +1191,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
{
if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce is not null)
{
if(uce.picks != null && uce.picks.ContainsKey(queryPickID))
uce.picks.Remove(queryPickID);
if(uce.picksList is not null)
uce.picksList.Remove(queryPickID);
uce.picks?.Remove(queryPickID);
uce.picksList?.Remove(queryPickID);
m_profilesCache.AddOrUpdate(remoteClient.AgentId, uce, PROFILECACHEEXPIRE);
}
}
@@ -1451,7 +1448,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
props = uce.props;
uint cflags = uce.flags;
if (IsFriendOnline(remoteClient.AgentId, avatarID))
if (IsFriendOnline(remoteClient, avatarID))
cflags = (uint)ProfileFlags.Online;
else
cflags &= (uint)~ProfileFlags.Online;
@@ -1831,22 +1828,21 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
return null;
}
public virtual bool IsFriendOnline(UUID client, UUID agent)
public virtual bool IsFriendOnline(IClientAPI client, UUID agent)
{
// if on same region force online
// if on same region force online
ScenePresence p = Scene.GetScenePresence(agent);
if (p is not null && !p.IsDeleted)
if (p is not null && !p.IsChildAgent && !p.IsDeleted)
return true;
IFriendsModule friendsModule = Scene.RequestModuleInterface<IFriendsModule>();
if (friendsModule is not null)
if (friendsModule is not null && friendsModule.IsFriendOnline(client.AgentId, agent))
return true;
if(client.SceneAgent is ScenePresence sp && sp.IsViewerUIGod)
{
int friendPerms = friendsModule.GetRightsGrantedByFriend(client, agent);
if((friendPerms & (int)FriendRights.CanSeeOnline) != 0)
{
Services.Interfaces.PresenceInfo[] pi = Scene.PresenceService?.GetAgents(new string[] { agent.ToString() });
return pi is not null && pi.Length > 0;
}
Services.Interfaces.PresenceInfo[] pi = Scene.PresenceService?.GetAgents(new string[] { agent.ToString() });
return pi != null && pi.Length > 0;
}
return false;
}

View File

@@ -96,5 +96,8 @@ namespace OpenSim.Region.Framework.Interfaces
void IsNowRoot(ScenePresence sp);
bool SendFriendsOnlineIfNeeded(IClientAPI client);
bool IsFriendOnline(UUID userID, UUID friendID);
void CacheFriendsOnline(UUID userID, List<UUID> friendsOnline, bool online);
void CacheFriendOnline(UUID userID, UUID friendOnline, bool online);
}
}