split userprofiles request queues into local and HG, add console debug comand profiles status to check size of those queues
Some checks failed
.msbuildnet6 / build (push) Has been cancelled
Some checks failed
.msbuildnet6 / build (push) Has been cancelled
This commit is contained in:
@@ -45,7 +45,6 @@ using OpenSim.Services.Connectors.Hypergrid;
|
|||||||
using OpenSim.Framework.Servers.HttpServer;
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
using OpenSim.Services.UserProfilesService;
|
using OpenSim.Services.UserProfilesService;
|
||||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||||
using OpenSim.Region.CoreModules.Avatar.Friends;
|
|
||||||
|
|
||||||
namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
|
namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
|
||||||
{
|
{
|
||||||
@@ -61,8 +60,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
|
|||||||
// The pair of Dictionaries are used to handle the switching of classified ads
|
// The pair of Dictionaries are used to handle the switching of classified ads
|
||||||
// by maintaining a cache of classified id to creator id mappings and an interest
|
// by maintaining a cache of classified id to creator id mappings and an interest
|
||||||
// count. The entries are removed when the interest count reaches 0.
|
// count. The entries are removed when the interest count reaches 0.
|
||||||
readonly Dictionary<UUID, UUID> m_classifiedCache = new();
|
readonly Dictionary<UUID, UUID> m_classifiedCache = [];
|
||||||
readonly Dictionary<UUID, int> m_classifiedInterest = new();
|
readonly Dictionary<UUID, int> m_classifiedInterest = [];
|
||||||
readonly ExpiringCacheOS<UUID, UserProfileCacheEntry> m_profilesCache = new(60000);
|
readonly ExpiringCacheOS<UUID, UserProfileCacheEntry> m_profilesCache = new(60000);
|
||||||
|
|
||||||
IGroupsModule m_groupsModule = null;
|
IGroupsModule m_groupsModule = null;
|
||||||
@@ -79,128 +78,150 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
|
|||||||
public int reqtype;
|
public int reqtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly ConcurrentStack<AsyncPropsRequest> m_asyncRequests = new();
|
private readonly ConcurrentStack<AsyncPropsRequest> m_asyncLocalRequests = new();
|
||||||
private readonly object m_asyncRequestsLock = new();
|
private readonly object m_asyncLocalRequestsLock = new();
|
||||||
private bool m_asyncRequestsRunning = false;
|
private bool m_asyncLocalRequestsRunning = false;
|
||||||
|
private readonly ConcurrentStack<AsyncPropsRequest> m_asyncHGRequests = new();
|
||||||
|
private readonly object m_asyncHGRequestsLock = new();
|
||||||
|
private bool m_asyncHGRequestsRunning = false;
|
||||||
|
|
||||||
private void ProcessRequests()
|
private void ProcessLocalRequests()
|
||||||
{
|
{
|
||||||
lock(m_asyncRequestsLock)
|
lock(m_asyncLocalRequestsLock)
|
||||||
{
|
{
|
||||||
while (m_asyncRequests.TryPop(out AsyncPropsRequest req))
|
while (m_asyncLocalRequests.TryPop(out AsyncPropsRequest req))
|
||||||
{
|
{
|
||||||
try
|
IClientAPI client = req.client;
|
||||||
|
if(!client.IsActive)
|
||||||
|
continue;
|
||||||
|
ProcessRequest(req);
|
||||||
|
}
|
||||||
|
m_asyncLocalRequestsRunning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessHGRequests()
|
||||||
|
{
|
||||||
|
lock(m_asyncHGRequestsLock)
|
||||||
|
{
|
||||||
|
while (m_asyncHGRequests.TryPop(out AsyncPropsRequest req))
|
||||||
|
{
|
||||||
|
IClientAPI client = req.client;
|
||||||
|
if(!client.IsActive)
|
||||||
|
continue;
|
||||||
|
ProcessRequest(req);
|
||||||
|
}
|
||||||
|
m_asyncHGRequestsRunning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessRequest(AsyncPropsRequest req)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IClientAPI client = req.client;
|
||||||
|
if(req.reqtype == 0)
|
||||||
|
{
|
||||||
|
ScenePresence p = req.presence;
|
||||||
|
|
||||||
|
bool foreign = GetUserProfileServerURI(req.agent, out string serverURI);
|
||||||
|
bool ok = serverURI.Length > 0;
|
||||||
|
|
||||||
|
byte[] membershipType = new byte[1];
|
||||||
|
string born = string.Empty;
|
||||||
|
uint flags = 0x00;
|
||||||
|
|
||||||
|
if (ok && GetUserAccountData(req.agent, out UserAccount acc))
|
||||||
{
|
{
|
||||||
IClientAPI client = req.client;
|
flags = (uint)(acc.UserFlags & 0xff);
|
||||||
if(!client.IsActive)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(req.reqtype == 0)
|
if (acc.UserTitle.Length == 0)
|
||||||
|
membershipType[0] = (byte)((acc.UserFlags & 0x0f00) >> 8);
|
||||||
|
else
|
||||||
|
membershipType = Utils.StringToBytes(acc.UserTitle);
|
||||||
|
|
||||||
|
int val_born = acc.Created;
|
||||||
|
if (val_born != 0)
|
||||||
|
born = Util.ToDateTime(val_born).ToString("M/d/yyyy", CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ok = false;
|
||||||
|
|
||||||
|
UserProfileProperties props = new() { UserId = req.agent };
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
ok = GetProfileData(ref props, foreign, serverURI, out string result);
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
props.AboutText = "Profile not available at this time. User may still be unknown to this grid";
|
||||||
|
|
||||||
|
if (!m_allowUserProfileWebURLs)
|
||||||
|
props.WebUrl = "";
|
||||||
|
|
||||||
|
GroupMembershipData[] agentGroups = null;
|
||||||
|
if(ok && m_groupsModule is not null)
|
||||||
|
agentGroups = m_groupsModule.GetMembershipData(req.agent);
|
||||||
|
|
||||||
|
HashSet<IClientAPI> clients;
|
||||||
|
lock (m_profilesCache)
|
||||||
|
{
|
||||||
|
if (!m_profilesCache.TryGetValue(props.UserId, out UserProfileCacheEntry uce) || uce is null)
|
||||||
|
uce = new UserProfileCacheEntry();
|
||||||
|
uce.props = props;
|
||||||
|
uce.born = born;
|
||||||
|
uce.membershipType = membershipType;
|
||||||
|
uce.flags = flags;
|
||||||
|
clients = uce.ClientsWaitingProps;
|
||||||
|
uce.ClientsWaitingProps = null;
|
||||||
|
uce.avatarGroups = agentGroups;
|
||||||
|
m_profilesCache.AddOrUpdate(props.UserId, uce, PROFILECACHEEXPIRE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsFriendOnline(req.client, req.agent))
|
||||||
|
flags |= (uint)ProfileFlags.Online;
|
||||||
|
else
|
||||||
|
flags &= (uint)~ProfileFlags.Online;
|
||||||
|
|
||||||
|
if (clients is null)
|
||||||
|
{
|
||||||
|
client.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType, props.FirstLifeText, flags,
|
||||||
|
props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
|
||||||
|
|
||||||
|
client.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
|
||||||
|
(uint)props.SkillsMask, props.SkillsText, props.Language);
|
||||||
|
if (agentGroups is not null)
|
||||||
|
client.SendAvatarGroupsReply(req.agent, agentGroups);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!clients.Contains(client) && client.IsActive)
|
||||||
{
|
{
|
||||||
ScenePresence p = req.presence;
|
client.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType, props.FirstLifeText, flags,
|
||||||
|
props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
|
||||||
|
|
||||||
bool foreign = GetUserProfileServerURI(req.agent, out string serverURI);
|
client.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
|
||||||
bool ok = serverURI.Length > 0;
|
(uint)props.SkillsMask, props.SkillsText, props.Language);
|
||||||
|
if (agentGroups is not null)
|
||||||
|
client.SendAvatarGroupsReply(req.agent, agentGroups);
|
||||||
|
}
|
||||||
|
foreach (IClientAPI cli in clients)
|
||||||
|
{
|
||||||
|
if (!cli.IsActive)
|
||||||
|
continue;
|
||||||
|
cli.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType, props.FirstLifeText, flags,
|
||||||
|
props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
|
||||||
|
|
||||||
byte[] membershipType = new byte[1];
|
cli.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
|
||||||
string born = string.Empty;
|
(uint)props.SkillsMask, props.SkillsText, props.Language);
|
||||||
uint flags = 0x00;
|
if (agentGroups is not null)
|
||||||
|
cli.SendAvatarGroupsReply(req.agent, agentGroups);
|
||||||
if (ok && GetUserAccountData(req.agent, out UserAccount acc))
|
|
||||||
{
|
|
||||||
flags = (uint)(acc.UserFlags & 0xff);
|
|
||||||
|
|
||||||
if (acc.UserTitle.Length == 0)
|
|
||||||
membershipType[0] = (byte)((acc.UserFlags & 0x0f00) >> 8);
|
|
||||||
else
|
|
||||||
membershipType = Utils.StringToBytes(acc.UserTitle);
|
|
||||||
|
|
||||||
int val_born = acc.Created;
|
|
||||||
if (val_born != 0)
|
|
||||||
born = Util.ToDateTime(val_born).ToString("M/d/yyyy", CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ok = false;
|
|
||||||
|
|
||||||
UserProfileProperties props = new() { UserId = req.agent };
|
|
||||||
|
|
||||||
if (ok)
|
|
||||||
ok = GetProfileData(ref props, foreign, serverURI, out string result);
|
|
||||||
|
|
||||||
if (!ok)
|
|
||||||
props.AboutText = "Profile not available at this time. User may still be unknown to this grid";
|
|
||||||
|
|
||||||
if (!m_allowUserProfileWebURLs)
|
|
||||||
props.WebUrl = "";
|
|
||||||
|
|
||||||
GroupMembershipData[] agentGroups = null;
|
|
||||||
if(ok && m_groupsModule is not null)
|
|
||||||
agentGroups = m_groupsModule.GetMembershipData(req.agent);
|
|
||||||
|
|
||||||
HashSet<IClientAPI> clients;
|
|
||||||
lock (m_profilesCache)
|
|
||||||
{
|
|
||||||
if (!m_profilesCache.TryGetValue(props.UserId, out UserProfileCacheEntry uce) || uce is null)
|
|
||||||
uce = new UserProfileCacheEntry();
|
|
||||||
uce.props = props;
|
|
||||||
uce.born = born;
|
|
||||||
uce.membershipType = membershipType;
|
|
||||||
uce.flags = flags;
|
|
||||||
clients = uce.ClientsWaitingProps;
|
|
||||||
uce.ClientsWaitingProps = null;
|
|
||||||
uce.avatarGroups = agentGroups;
|
|
||||||
m_profilesCache.AddOrUpdate(props.UserId, uce, PROFILECACHEEXPIRE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsFriendOnline(req.client, req.agent))
|
|
||||||
flags |= (uint)ProfileFlags.Online;
|
|
||||||
else
|
|
||||||
flags &= (uint)~ProfileFlags.Online;
|
|
||||||
|
|
||||||
if (clients is null)
|
|
||||||
{
|
|
||||||
client.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType, props.FirstLifeText, flags,
|
|
||||||
props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
|
|
||||||
|
|
||||||
client.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
|
|
||||||
(uint)props.SkillsMask, props.SkillsText, props.Language);
|
|
||||||
if (agentGroups is not null)
|
|
||||||
client.SendAvatarGroupsReply(req.agent, agentGroups);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!clients.Contains(client) && client.IsActive)
|
|
||||||
{
|
|
||||||
client.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType, props.FirstLifeText, flags,
|
|
||||||
props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
|
|
||||||
|
|
||||||
client.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
|
|
||||||
(uint)props.SkillsMask, props.SkillsText, props.Language);
|
|
||||||
if (agentGroups is not null)
|
|
||||||
client.SendAvatarGroupsReply(req.agent, agentGroups);
|
|
||||||
}
|
|
||||||
foreach (IClientAPI cli in clients)
|
|
||||||
{
|
|
||||||
if (!cli.IsActive)
|
|
||||||
continue;
|
|
||||||
cli.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType, props.FirstLifeText, flags,
|
|
||||||
props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
|
|
||||||
|
|
||||||
cli.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
|
|
||||||
(uint)props.SkillsMask, props.SkillsText, props.Language);
|
|
||||||
if (agentGroups is not null)
|
|
||||||
cli.SendAvatarGroupsReply(req.agent, agentGroups);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
m_log.ErrorFormat("[UserProfileModule]: Process fail {0} : {1}", e.Message, e.StackTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
m_asyncRequestsRunning = false;
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
m_log.Error($"[UserProfileModule]: Process fail {e.Message} : {e.StackTrace}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +264,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
|
|||||||
public bool Enabled
|
public bool Enabled
|
||||||
{
|
{
|
||||||
get;
|
get;
|
||||||
set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
private GridInfo m_thisGridInfo;
|
private GridInfo m_thisGridInfo;
|
||||||
@@ -260,7 +281,6 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
|
|||||||
public void Initialise(IConfigSource source)
|
public void Initialise(IConfigSource source)
|
||||||
{
|
{
|
||||||
Config = source;
|
Config = source;
|
||||||
ReplaceableInterface = typeof(IProfileModule);
|
|
||||||
|
|
||||||
IConfig profileConfig = Config.Configs["UserProfiles"];
|
IConfig profileConfig = Config.Configs["UserProfiles"];
|
||||||
|
|
||||||
@@ -292,10 +312,19 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
|
|||||||
m_allowUserProfileWebURLs = profileConfig.GetBoolean("AllowUserProfileWebURLs", m_allowUserProfileWebURLs);
|
m_allowUserProfileWebURLs = profileConfig.GetBoolean("AllowUserProfileWebURLs", m_allowUserProfileWebURLs);
|
||||||
|
|
||||||
m_log.Debug("[UserProfileModule]: Full Profiles Enabled");
|
m_log.Debug("[UserProfileModule]: Full Profiles Enabled");
|
||||||
ReplaceableInterface = null;
|
|
||||||
|
MainConsole.Instance.Commands.AddCommand("Debug", false, "profiles status",
|
||||||
|
"profiles status",
|
||||||
|
"Show user profile Queues count",
|
||||||
|
HandleShowStatus);
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleShowStatus(string module, string[] cmdparms)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.Output($"Profile requests in '{Scene.Name}' Local: {m_asyncLocalRequests.Count} HG: {m_asyncHGRequests.Count}");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the region.
|
/// Adds the region.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -369,7 +398,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
|
|||||||
/// </value>
|
/// </value>
|
||||||
public Type ReplaceableInterface
|
public Type ReplaceableInterface
|
||||||
{
|
{
|
||||||
get; private set;
|
get { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -1645,131 +1674,47 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
|
|||||||
agent = avatarID,
|
agent = avatarID,
|
||||||
reqtype = 0
|
reqtype = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
m_asyncRequests.Push(req);
|
|
||||||
|
|
||||||
if (Monitor.TryEnter(m_asyncRequestsLock))
|
if(m_userManagementModule.IsLocalGridUser(avatarID))
|
||||||
{
|
{
|
||||||
try
|
m_asyncLocalRequests.Push(req);
|
||||||
|
|
||||||
|
if (Monitor.TryEnter(m_asyncLocalRequestsLock))
|
||||||
{
|
{
|
||||||
if (!m_asyncRequestsRunning)
|
try
|
||||||
{
|
{
|
||||||
m_asyncRequestsRunning = true;
|
if (!m_asyncLocalRequestsRunning)
|
||||||
Util.FireAndForget(x => ProcessRequests());
|
{
|
||||||
|
m_asyncLocalRequestsRunning = true;
|
||||||
|
Util.FireAndForget(x => ProcessLocalRequests());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Monitor.Exit(m_asyncLocalRequestsLock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
Monitor.Exit(m_asyncRequestsLock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
string serverURI = string.Empty;
|
|
||||||
bool foreign = GetUserProfileServerURI(avatarID, out serverURI);
|
|
||||||
|
|
||||||
UserAccount account = null;
|
|
||||||
Dictionary<string,object> userInfo;
|
|
||||||
|
|
||||||
if (!foreign)
|
|
||||||
{
|
|
||||||
account = Scene.UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, avatarID);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
userInfo = new Dictionary<string, object>();
|
m_asyncHGRequests.Push(req);
|
||||||
}
|
|
||||||
|
|
||||||
Byte[] membershipType = new Byte[1];
|
if (Monitor.TryEnter(m_asyncHGRequestsLock))
|
||||||
string born = string.Empty;
|
|
||||||
uint flags = 0x00;
|
|
||||||
|
|
||||||
if (null != account)
|
|
||||||
{
|
|
||||||
if (account.UserTitle.Length == 0)
|
|
||||||
membershipType[0] = (Byte)((account.UserFlags & 0xf00) >> 8);
|
|
||||||
else
|
|
||||||
membershipType = Utils.StringToBytes(account.UserTitle);
|
|
||||||
|
|
||||||
born = Util.ToDateTime(account.Created).ToString(
|
|
||||||
"M/d/yyyy", CultureInfo.InvariantCulture);
|
|
||||||
flags = (uint)(account.UserFlags & 0xff);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (GetUserAccountData(avatarID, out userInfo) == true)
|
|
||||||
{
|
{
|
||||||
if ((string)userInfo["user_title"].Length == 0)
|
try
|
||||||
membershipType[0] = (Byte)(((Byte)userInfo["user_flags"] & 0xf00) >> 8);
|
{
|
||||||
else
|
if (!m_asyncHGRequestsRunning)
|
||||||
membershipType = Utils.StringToBytes((string)userInfo["user_title"]);
|
{
|
||||||
|
m_asyncHGRequestsRunning = true;
|
||||||
int val_born = (int)userInfo["user_created"];
|
Util.FireAndForget(x => ProcessHGRequests());
|
||||||
if(val_born != 0)
|
}
|
||||||
born = Util.ToDateTime(val_born).ToString(
|
}
|
||||||
"M/d/yyyy", CultureInfo.InvariantCulture);
|
finally
|
||||||
|
{
|
||||||
// picky, picky
|
Monitor.Exit(m_asyncHGRequestsLock);
|
||||||
int val_flags = (int)userInfo["user_flags"];
|
}
|
||||||
flags = (uint)(val_flags & 0xff);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
props = new UserProfileProperties();
|
|
||||||
props.UserId = avatarID;
|
|
||||||
|
|
||||||
string result = string.Empty;
|
|
||||||
if(!GetProfileData(ref props, foreign, serverURI, out result))
|
|
||||||
{
|
|
||||||
props.AboutText ="Profile not available at this time. User may still be unknown to this grid";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!m_allowUserProfileWebURLs)
|
|
||||||
props.WebUrl ="";
|
|
||||||
|
|
||||||
HashSet<IClientAPI> clients;
|
|
||||||
lock(m_profilesCache)
|
|
||||||
{
|
|
||||||
if(!m_profilesCache.TryGetValue(props.UserId, out uce) || uce == null)
|
|
||||||
uce = new UserProfileCacheEntry();
|
|
||||||
uce.props = props;
|
|
||||||
uce.born = born;
|
|
||||||
uce.membershipType = membershipType;
|
|
||||||
uce.flags = flags;
|
|
||||||
clients = uce.ClientsWaitingProps;
|
|
||||||
uce.ClientsWaitingProps = null;
|
|
||||||
m_profilesCache.AddOrUpdate(props.UserId, uce, PROFILECACHEEXPIRE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if on same region force online
|
|
||||||
if(p != null && !p.IsDeleted)
|
|
||||||
flags |= 0x10;
|
|
||||||
|
|
||||||
if(clients == null)
|
|
||||||
{
|
|
||||||
remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags,
|
|
||||||
props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
|
|
||||||
|
|
||||||
remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
|
|
||||||
(uint)props.SkillsMask, props.SkillsText, props.Language);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(!clients.Contains(remoteClient))
|
|
||||||
clients.Add(remoteClient);
|
|
||||||
foreach(IClientAPI cli in clients)
|
|
||||||
{
|
|
||||||
if(!cli.IsActive)
|
|
||||||
continue;
|
|
||||||
cli.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags,
|
|
||||||
props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId);
|
|
||||||
|
|
||||||
cli.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText,
|
|
||||||
(uint)props.SkillsMask, props.SkillsText, props.Language);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user