Fix friends again. Friends-handling is now stateless and, thanks to
MessageTransferModule, much easier to understand (I hope).0.6.1-post-fixes
parent
4d23d22fb1
commit
07afe9c137
|
@ -101,7 +101,6 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends
|
|||
|
||||
private Dictionary<UUID, ulong> m_rootAgents = new Dictionary<UUID, ulong>();
|
||||
|
||||
private Dictionary<UUID, Transaction> m_pendingFriendRequests = new Dictionary<UUID, Transaction>();
|
||||
private Dictionary<UUID, UUID> m_pendingCallingcardRequests = new Dictionary<UUID,UUID>();
|
||||
|
||||
private Scene m_initialScene; // saves a lookup if we don't have a specific scene
|
||||
|
@ -263,7 +262,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends
|
|||
// to a user to 'add a friend' without causing dialog box spam
|
||||
|
||||
// Subscribe to instant messages
|
||||
// client.OnInstantMessage += OnInstantMessage;
|
||||
client.OnInstantMessage += OnInstantMessage;
|
||||
|
||||
// Friend list management
|
||||
client.OnApproveFriendRequest += OnApproveFriendRequest;
|
||||
|
@ -369,233 +368,143 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends
|
|||
|
||||
#region FriendRequestHandling
|
||||
|
||||
private void OnInstantMessage(IClientAPI client, UUID fromAgentID,
|
||||
UUID toAgentID,
|
||||
UUID imSessionID, uint timestamp, string fromAgentName,
|
||||
string message, byte dialog, bool fromGroup, byte offline,
|
||||
uint ParentEstateID, Vector3 Position, UUID RegionID,
|
||||
byte[] binaryBucket)
|
||||
private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
|
||||
{
|
||||
// Friend Requests go by Instant Message.. using the dialog param
|
||||
// https://wiki.secondlife.com/wiki/ImprovedInstantMessage
|
||||
UUID fromAgentID = new UUID(im.fromAgentID);
|
||||
UUID toAgentID = new UUID(im.toAgentID);
|
||||
|
||||
if (dialog == (byte)InstantMessageDialog.FriendshipOffered) // 38
|
||||
if (im.dialog == (byte)InstantMessageDialog.FriendshipOffered) // 38
|
||||
{
|
||||
// this is triggered by the initiating agent and has two parts:
|
||||
// this is triggered by the initiating agent:
|
||||
// A local agent offers friendship to some possibly remote friend.
|
||||
// A IM is triggered, processed here (1), sent to the destination region,
|
||||
// and processed there in this part of the code again (2).
|
||||
// (1) has fromAgentSession != UUID.Zero,
|
||||
// (2) has fromAgentSession == UUID.Zero (don't leak agent sessions to other agents)
|
||||
// For (1), build the IM to send to the other region (and trigger sending it)
|
||||
// FOr (2), just store the transaction; we will wait for Approval or Decline
|
||||
// A IM is triggered, processed here and sent to the friend (possibly in a remote region).
|
||||
|
||||
// some properties are misused here:
|
||||
// fromAgentName is the *destination* name (the friend we offer friendship to)
|
||||
|
||||
// (1)
|
||||
// send the friendship-offer to the target
|
||||
m_log.InfoFormat("[FRIEND]: Offer(38) - From: {0}, FromName: {1} To: {2}, Session: {3}, Message: {4}, Offline {5}",
|
||||
fromAgentID, fromAgentName, toAgentID, imSessionID, message, offline);
|
||||
|
||||
UUID transactionID = UUID.Random();
|
||||
im.fromAgentID, im.fromAgentName, im.toAgentID, im.imSessionID, im.message, im.offline);
|
||||
|
||||
// 1.20 protocol sends an UUID in the message field, instead of the friendship offer text.
|
||||
// For interoperability, we have to clear that
|
||||
if (Util.isUUID(message)) message = "";
|
||||
if (Util.isUUID(im.message)) im.message = "";
|
||||
|
||||
GridInstantMessage msg = new GridInstantMessage();
|
||||
msg.fromAgentID = fromAgentID.Guid;
|
||||
msg.toAgentID = toAgentID.Guid;
|
||||
msg.imSessionID = transactionID.Guid; // Start new transaction
|
||||
m_log.DebugFormat("[FRIEND]: new transactionID: {0}", msg.imSessionID);
|
||||
msg.timestamp = timestamp;
|
||||
if (client != null)
|
||||
{
|
||||
msg.fromAgentName = client.Name; // fromAgentName;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.fromAgentName = "(hippos)"; // Added for posterity. This means that we can't figure out who sent it
|
||||
}
|
||||
msg.message = message;
|
||||
msg.dialog = dialog;
|
||||
msg.fromGroup = fromGroup;
|
||||
msg.offline = offline;
|
||||
msg.ParentEstateID = ParentEstateID;
|
||||
msg.Position = Position;
|
||||
msg.RegionID = RegionID.Guid;
|
||||
msg.binaryBucket = binaryBucket;
|
||||
// be sneeky and use the initiator-UUID as transactionID. This means we can be stateless.
|
||||
// we have to look up the agent name on friendship-approval, though.
|
||||
im.imSessionID = im.fromAgentID;
|
||||
im.fromAgentName = client.Name;
|
||||
|
||||
m_log.DebugFormat("[FRIEND]: storing transactionID {0} on sender side", transactionID);
|
||||
lock (m_pendingFriendRequests)
|
||||
{
|
||||
m_pendingFriendRequests.Add(transactionID, new Transaction(fromAgentID, fromAgentName));
|
||||
outPending();
|
||||
}
|
||||
|
||||
// we don't want to get that new IM into here if we aren't local, as only on the destination
|
||||
// should receive it. If we *are* local, *we* are the destination, so we have to receive it.
|
||||
// As grid-IMs are routed to all modules (in contrast to local IMs), we have to decide here.
|
||||
|
||||
// We don't really care which local scene we pipe it through.
|
||||
if (m_TransferModule != null)
|
||||
{
|
||||
m_TransferModule.SendInstantMessage(msg,
|
||||
delegate(bool success) {}
|
||||
// Send it to whoever is the destination.
|
||||
// If new friend is local, it will send an IM to the viewer.
|
||||
// If new friend is remote, it will cause a OnGridInstantMessage on the remote server
|
||||
m_TransferModule.SendInstantMessage(im,
|
||||
delegate(bool success) {
|
||||
m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (dialog == (byte)InstantMessageDialog.FriendshipAccepted) // 39
|
||||
else if (im.dialog == (byte)InstantMessageDialog.FriendshipAccepted) // 39
|
||||
{
|
||||
// accepting the friendship offer causes a type 39 IM being sent to the (possibly remote) initiator
|
||||
// toAgentID is initiator, fromAgentID is new friend (which just approved)
|
||||
m_log.DebugFormat("[FRIEND]: 39 - from client {0}, agent {1} {2}, imsession {3} to {4}: {5} (dialog {6})",
|
||||
client != null ? client.AgentId.ToString() : "<null>",
|
||||
fromAgentID, fromAgentName, imSessionID, toAgentID, message, dialog);
|
||||
lock (m_pendingFriendRequests)
|
||||
{
|
||||
if (!m_pendingFriendRequests.ContainsKey(imSessionID))
|
||||
{
|
||||
m_log.DebugFormat("[FRIEND]: Got friendship approval from {0} to {1} without matching transaction {2}",
|
||||
fromAgentID, toAgentID, imSessionID);
|
||||
return; // unknown transaction
|
||||
}
|
||||
// else found pending friend request with that transaction => remove it if we handled all
|
||||
if (--m_pendingFriendRequests[imSessionID].count <= 0) m_pendingFriendRequests.Remove(imSessionID);
|
||||
outPending();
|
||||
}
|
||||
m_log.DebugFormat("[FRIEND]: 39 - from client {0}, agent {2} {3}, imsession {4} to {5}: {6} (dialog {7})",
|
||||
client.AgentId, im.fromAgentID, im.fromAgentName, im.imSessionID, im.toAgentID, im.message, im.dialog);
|
||||
|
||||
// a new friend was added in the initiator's and friend's data, so the cache entries are wrong now.
|
||||
lock (m_friendLists)
|
||||
{
|
||||
m_friendLists.Invalidate(toAgentID);
|
||||
m_friendLists.Invalidate(fromAgentID);
|
||||
}
|
||||
|
||||
// now send presence update and add a calling card for the new friend
|
||||
|
||||
ScenePresence initiator = GetAnyPresenceFromAgentID(toAgentID);
|
||||
if (initiator == null)
|
||||
{
|
||||
// quite wrong. Shouldn't happen.
|
||||
m_log.WarnFormat("[FRIEND]: Coudn't find initiator of friend request {0}", toAgentID);
|
||||
return;
|
||||
}
|
||||
|
||||
// tell initiator that friend is online
|
||||
initiator.ControllingClient.SendAgentOnline(new UUID[] { fromAgentID });
|
||||
|
||||
// find the folder for the friend...
|
||||
InventoryFolderImpl folder =
|
||||
initiator.Scene.CommsManager.UserProfileCacheService.GetUserDetails(toAgentID).FindFolderForType((int)InventoryType.CallingCard);
|
||||
if (folder != null)
|
||||
{
|
||||
// ... and add the calling card
|
||||
CreateCallingCard(initiator.ControllingClient, fromAgentID, folder.ID, fromAgentName);
|
||||
}
|
||||
}
|
||||
else if (dialog == (byte)InstantMessageDialog.FriendshipDeclined) // 40
|
||||
else if (im.dialog == (byte)InstantMessageDialog.FriendshipDeclined) // 40
|
||||
{
|
||||
// declining the friendship offer causes a type 40 IM being sent to the (possibly remote) initiator
|
||||
// toAgentID is initiator, fromAgentID declined friendship
|
||||
m_log.DebugFormat("[FRIEND]: 40 - from client {0}, agent {1} {2}, imsession {3} to {4}: {5} (dialog {6})",
|
||||
client != null ? client.AgentId.ToString() : "<null>",
|
||||
fromAgentID, fromAgentName, imSessionID, toAgentID, message, dialog);
|
||||
fromAgentID, im.fromAgentName, im.imSessionID, im.toAgentID, im.message, im.dialog);
|
||||
|
||||
// not much to do, just clean up the transaction...
|
||||
lock (m_pendingFriendRequests)
|
||||
{
|
||||
if (!m_pendingFriendRequests.ContainsKey(imSessionID))
|
||||
{
|
||||
m_log.DebugFormat("[FRIEND]: Got friendship denial from {0} to {1} without matching transaction {2}",
|
||||
fromAgentID, toAgentID, imSessionID);
|
||||
return; // unknown transaction
|
||||
// Send the decline to whoever is the destination.
|
||||
GridInstantMessage msg = new GridInstantMessage(client.Scene, fromAgentID, client.Name, toAgentID,
|
||||
im.dialog, im.message, im.offline != 0, im.Position);
|
||||
// If new friend is local, it will send an IM to the viewer.
|
||||
// If new friend is remote, it will cause a OnGridInstantMessage on the remote server
|
||||
m_TransferModule.SendInstantMessage(msg,
|
||||
delegate(bool success) {
|
||||
m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
|
||||
}
|
||||
// else found pending friend request with that transaction => remove it if we handled all
|
||||
if (--m_pendingFriendRequests[imSessionID].count <= 0) m_pendingFriendRequests.Remove(imSessionID);
|
||||
outPending();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGridInstantMessage(GridInstantMessage msg)
|
||||
{
|
||||
if (msg.dialog == (byte)InstantMessageDialog.FriendshipOffered)
|
||||
{
|
||||
// we are on the receiving end here; just add the transactionID
|
||||
// to the stored transactions for later lookup
|
||||
//
|
||||
m_log.DebugFormat("[FRIEND]: storing transactionID {0} on "+
|
||||
"receiver side", msg.imSessionID);
|
||||
|
||||
lock (m_pendingFriendRequests)
|
||||
{
|
||||
// if both are on the same region-server, the transaction
|
||||
// is stored already, but we have to update the name
|
||||
//
|
||||
if (m_pendingFriendRequests.ContainsKey(
|
||||
new UUID(msg.imSessionID)))
|
||||
{
|
||||
m_pendingFriendRequests[new UUID(msg.imSessionID)].agentName =
|
||||
msg.fromAgentName;
|
||||
m_pendingFriendRequests[new UUID(msg.imSessionID)].count++;
|
||||
}
|
||||
else m_pendingFriendRequests.Add(new UUID(msg.imSessionID),
|
||||
new Transaction(new UUID(msg.fromAgentID),
|
||||
msg.fromAgentName));
|
||||
|
||||
outPending();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Just call the IM handler above
|
||||
// This event won't be raised unless we have that agent,
|
||||
// so we can depend on the above not trying to send
|
||||
// via grid again
|
||||
//
|
||||
OnInstantMessage(null, new UUID(msg.fromAgentID),
|
||||
new UUID(msg.toAgentID), new UUID(msg.imSessionID),
|
||||
msg.timestamp, msg.fromAgentName, msg.message,
|
||||
msg.dialog, msg.fromGroup, msg.offline,
|
||||
msg.ParentEstateID, msg.Position,
|
||||
new UUID(msg.RegionID), msg.binaryBucket);
|
||||
m_log.DebugFormat("[FRIEND]: Got GridIM from {0}, to {1}, imSession {2}, message {3}, dialog {4}",
|
||||
msg.fromAgentID, msg.toAgentID, msg.imSessionID, msg.message, msg.dialog);
|
||||
if (msg.dialog == (byte)InstantMessageDialog.FriendshipOffered ||
|
||||
msg.dialog == (byte)InstantMessageDialog.FriendshipAccepted ||
|
||||
msg.dialog == (byte)InstantMessageDialog.FriendshipDeclined)
|
||||
{
|
||||
// this should succeed as we *know* the root agent is here.
|
||||
m_TransferModule.SendInstantMessage(msg,
|
||||
delegate(bool success) {
|
||||
m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (msg.dialog == (byte)InstantMessageDialog.FriendshipAccepted)
|
||||
{
|
||||
// for accept friendship, we have to do a bit more
|
||||
approveFriendship(new UUID(msg.fromAgentID), new UUID(msg.toAgentID), msg.fromAgentName);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID transactionID, List<UUID> callingCardFolders)
|
||||
private void approveFriendship(UUID fromAgentID, UUID toAgentID, string fromName)
|
||||
{
|
||||
m_log.DebugFormat("[FRIEND]: Approve friendship from {0} (ID: {1}) to {2}",
|
||||
fromAgentID, fromName, toAgentID);
|
||||
|
||||
// a new friend was added in the initiator's and friend's data, so the cache entries are wrong now.
|
||||
lock (m_friendLists)
|
||||
{
|
||||
m_friendLists.Invalidate(fromAgentID);
|
||||
m_friendLists.Invalidate(toAgentID);
|
||||
}
|
||||
|
||||
// now send presence update and add a calling card for the new friend
|
||||
|
||||
ScenePresence initiator = GetAnyPresenceFromAgentID(toAgentID);
|
||||
if (initiator == null)
|
||||
{
|
||||
// quite wrong. Shouldn't happen.
|
||||
m_log.WarnFormat("[FRIEND]: Coudn't find initiator of friend request {0}", toAgentID);
|
||||
return;
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[FRIEND]: Tell {0} that {1} is online",
|
||||
initiator.Name, fromName);
|
||||
// tell initiator that friend is online
|
||||
initiator.ControllingClient.SendAgentOnline(new UUID[] { fromAgentID });
|
||||
|
||||
// find the folder for the friend...
|
||||
InventoryFolderImpl folder =
|
||||
initiator.Scene.CommsManager.UserProfileCacheService.GetUserDetails(toAgentID).FindFolderForType((int)InventoryType.CallingCard);
|
||||
if (folder != null)
|
||||
{
|
||||
// ... and add the calling card
|
||||
CreateCallingCard(initiator.ControllingClient, fromAgentID, folder.ID, fromName);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
|
||||
{
|
||||
m_log.DebugFormat("[FRIEND]: Got approve friendship from {0} {1}, agentID {2}, tid {3}",
|
||||
client.Name, client.AgentId, agentID, transactionID);
|
||||
Transaction transaction;
|
||||
lock (m_pendingFriendRequests)
|
||||
{
|
||||
if (!m_pendingFriendRequests.TryGetValue(transactionID, out transaction))
|
||||
{
|
||||
m_log.DebugFormat("[FRIEND]: Got friendship approval {0} from {1} ({2}) without matching transaction {3}",
|
||||
agentID, client.AgentId, client.Name, transactionID);
|
||||
return; // unknown transaction
|
||||
}
|
||||
// else found pending friend request with that transaction => remove if done with all
|
||||
if (--m_pendingFriendRequests[transactionID].count <= 0) m_pendingFriendRequests.Remove(transactionID);
|
||||
outPending();
|
||||
}
|
||||
|
||||
UUID friendID = transaction.agentID;
|
||||
m_log.DebugFormat("[FRIEND]: {0} ({1}) approved friendship request from {2}",
|
||||
client.Name, client.AgentId, friendID);
|
||||
|
||||
Scene SceneAgentIn = m_initialScene;
|
||||
// we need any presence to send the packets to, not necessarily the root agent...
|
||||
ScenePresence agentpresence = GetAnyPresenceFromAgentID(agentID);
|
||||
if (agentpresence != null)
|
||||
{
|
||||
SceneAgentIn = agentpresence.Scene;
|
||||
}
|
||||
client.Name, client.AgentId, agentID, friendID);
|
||||
|
||||
// store the new friend persistently for both avatars
|
||||
SceneAgentIn.StoreAddFriendship(friendID, agentID, (uint) FriendRights.CanSeeOnline);
|
||||
m_initialScene.StoreAddFriendship(friendID, agentID, (uint) FriendRights.CanSeeOnline);
|
||||
|
||||
// The cache entries aren't valid anymore either, as we just added a friend to both sides.
|
||||
lock (m_friendLists)
|
||||
|
@ -604,94 +513,67 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends
|
|||
m_friendLists.Invalidate(friendID);
|
||||
}
|
||||
|
||||
// create calling card
|
||||
CreateCallingCard(client, friendID, callingCardFolders[0], transaction.agentName);
|
||||
// if it's a local friend, we don't have to do the lookup
|
||||
ScenePresence friendPresence = GetAnyPresenceFromAgentID(friendID);
|
||||
|
||||
// Compose response to other agent.
|
||||
GridInstantMessage msg = new GridInstantMessage();
|
||||
msg.toAgentID = friendID.Guid;
|
||||
msg.fromAgentID = agentID.Guid;
|
||||
msg.fromAgentName = client.Name;
|
||||
msg.fromGroup = false;
|
||||
msg.imSessionID = transactionID.Guid;
|
||||
msg.message = agentID.Guid.ToString();
|
||||
msg.ParentEstateID = 0;
|
||||
msg.timestamp = (uint) Util.UnixTimeSinceEpoch();
|
||||
msg.RegionID = SceneAgentIn.RegionInfo.RegionID.Guid;
|
||||
msg.dialog = (byte) InstantMessageDialog.FriendshipAccepted;
|
||||
msg.Position = Vector3.Zero;
|
||||
msg.offline = (byte) 0;
|
||||
msg.binaryBucket = new byte[0];
|
||||
|
||||
// we don't want to get that new IM into here if we aren't local, as only on the destination
|
||||
// should receive it. If we *are* local, *we* are the destination, so we have to receive it.
|
||||
// As grid-IMs are routed to all modules (in contrast to local IMs), we have to decide here.
|
||||
|
||||
// now we have to inform the agent about the friend. For the opposite direction, this happens in the handler
|
||||
// of the type 39 IM
|
||||
if (m_TransferModule != null)
|
||||
if(friendPresence != null)
|
||||
{
|
||||
m_TransferModule.SendInstantMessage(msg,
|
||||
delegate(bool success) {}
|
||||
);
|
||||
m_log.Debug("[FRIEND]: Local agent detected.");
|
||||
|
||||
// create calling card
|
||||
CreateCallingCard(client, friendID, callingCardFolders[0], friendPresence.Name);
|
||||
|
||||
// local message means OnGridInstantMessage won't be triggered, so do the work here.
|
||||
friendPresence.ControllingClient.SendInstantMessage(agentID, agentID.ToString(), friendID, client.Name,
|
||||
(byte)InstantMessageDialog.FriendshipAccepted,
|
||||
(uint)Util.UnixTimeSinceEpoch());
|
||||
approveFriendship(agentID, friendID, client.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Debug("[FRIEND]: Remote agent detected.");
|
||||
|
||||
// fetch the friend's name for the calling card.
|
||||
CachedUserInfo info = m_initialScene.CommsManager.UserProfileCacheService.GetUserDetails(friendID);
|
||||
|
||||
// create calling card
|
||||
CreateCallingCard(client, friendID, callingCardFolders[0],
|
||||
info.UserProfile.FirstName + " " + info.UserProfile.SurName);
|
||||
|
||||
// Compose (remote) response to friend.
|
||||
GridInstantMessage msg = new GridInstantMessage(client.Scene, agentID, client.Name, friendID,
|
||||
(byte)InstantMessageDialog.FriendshipAccepted,
|
||||
agentID.ToString(), false, Vector3.Zero);
|
||||
if (m_TransferModule != null)
|
||||
{
|
||||
m_TransferModule.SendInstantMessage(msg,
|
||||
delegate(bool success) {
|
||||
m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// tell client that new friend is online
|
||||
client.SendAgentOnline(new UUID[] { friendID });
|
||||
}
|
||||
|
||||
private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID transactionID, List<UUID> callingCardFolders)
|
||||
private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
|
||||
{
|
||||
m_log.DebugFormat("[FRIEND]: Got deny friendship from {0} {1}, agentID {2}, tid {3}",
|
||||
client.Name, client.AgentId, agentID, transactionID);
|
||||
Transaction transaction;
|
||||
lock (m_pendingFriendRequests)
|
||||
{
|
||||
if (!m_pendingFriendRequests.TryGetValue(transactionID, out transaction))
|
||||
{
|
||||
m_log.DebugFormat("[FRIEND]: Got friendship denial {0} from {1} ({2}) without matching transaction {3}",
|
||||
agentID, client.AgentId, client.Name, transactionID);
|
||||
return;
|
||||
}
|
||||
// else found pending friend request with that transaction.
|
||||
if (--m_pendingFriendRequests[transactionID].count <= 0) m_pendingFriendRequests.Remove(transactionID);
|
||||
outPending();
|
||||
}
|
||||
UUID friendID = transaction.agentID;
|
||||
|
||||
Scene SceneAgentIn = m_initialScene;
|
||||
ScenePresence agentpresence = GetRootPresenceFromAgentID(agentID);
|
||||
if (agentpresence != null)
|
||||
{
|
||||
SceneAgentIn = agentpresence.Scene;
|
||||
}
|
||||
client.Name, client.AgentId, agentID, friendID);
|
||||
|
||||
// Compose response to other agent.
|
||||
GridInstantMessage msg = new GridInstantMessage();
|
||||
msg.toAgentID = friendID.Guid;
|
||||
msg.fromAgentID = agentID.Guid;
|
||||
msg.fromAgentName = client.Name;
|
||||
msg.fromGroup = false;
|
||||
msg.imSessionID = transactionID.Guid;
|
||||
msg.message = agentID.Guid.ToString();
|
||||
msg.ParentEstateID = 0;
|
||||
msg.timestamp = (uint) Util.UnixTimeSinceEpoch();
|
||||
msg.RegionID = SceneAgentIn.RegionInfo.RegionID.Guid;
|
||||
msg.dialog = (byte) InstantMessageDialog.FriendshipDeclined;
|
||||
msg.Position = Vector3.Zero;
|
||||
msg.offline = (byte) 0;
|
||||
msg.binaryBucket = new byte[0];
|
||||
|
||||
// we don't want to get that new IM into here if we aren't local, as only on the destination
|
||||
// should receive it. If we *are* local, *we* are the destination, so we have to receive it.
|
||||
// As grid-IMs are routed to all modules (in contrast to local IMs), we have to decide here.
|
||||
|
||||
// now we have to inform the agent about the friend. For the opposite direction, this happens in the handler
|
||||
// of the type 39 IM
|
||||
GridInstantMessage msg = new GridInstantMessage(client.Scene, agentID, client.Name, friendID,
|
||||
(byte)InstantMessageDialog.FriendshipDeclined,
|
||||
agentID.ToString(), false, Vector3.Zero);
|
||||
// send decline to initiator
|
||||
if (m_TransferModule != null)
|
||||
{
|
||||
m_TransferModule.SendInstantMessage(msg,
|
||||
delegate(bool success) {}
|
||||
delegate(bool success) {
|
||||
m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -824,8 +706,8 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends
|
|||
|
||||
private void OnDeclineCallingCard(IClientAPI client, UUID transactionID)
|
||||
{
|
||||
m_log.DebugFormat("[CALLING CARD]: User {0} declined card, tid {2}",
|
||||
client.AgentId, transactionID);
|
||||
m_log.DebugFormat("[CALLING CARD]: User {0} (ID:{1}) declined card, tid {2}",
|
||||
client.Name, client.AgentId, transactionID);
|
||||
UUID destID;
|
||||
lock (m_pendingCallingcardRequests)
|
||||
{
|
||||
|
@ -1040,16 +922,6 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Friends
|
|||
// tell everyone that we are offline
|
||||
SendPresenceState(remoteClient, fl, false);
|
||||
}
|
||||
|
||||
private void outPending()
|
||||
{
|
||||
m_log.DebugFormat("[FRIEND]: got {0} requests pending", m_pendingFriendRequests.Count);
|
||||
foreach (KeyValuePair<UUID, Transaction> pair in m_pendingFriendRequests)
|
||||
{
|
||||
m_log.DebugFormat("[FRIEND]: tid={0}, agent={1}, name={2}, count={3}",
|
||||
pair.Key, pair.Value.agentID, pair.Value.agentName, pair.Value.count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
Loading…
Reference in New Issue