You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

291 lines
13 KiB

using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Threading.Tasks;
using Sog;
using ProtoCSStruct;
namespace Friend
{
/// <summary>
/// 好友数据的内存cache
/// 处理逻辑是如果需要处理好友数据,那么先把数据拉取到内存,这样写起逻辑来比较简单,处理完后如果一段时间内不再访问,则淘汰
/// </summary>
public static class FriendCacheSvc
{
public static SSQueryFriendInfoCacheReq m_SSQueryFriendInfoCacheReq = new SSQueryFriendInfoCacheReq();
public static SSQueryFriendInfoCacheRes m_SSQueryFriendInfoCacheRes = new SSQueryFriendInfoCacheRes();
public static SSFriendOpReq m_SSFriendOpReq = new SSFriendOpReq();
public static void OnStop()
{
var cache = FriendServerUtils.GetFriendInfoCacheTable();
if (cache.ErrIconCount != 0)
{
TraceLog.Error("FriendCacheOp.OnStop error, ErrIconCount {0}", cache.ErrIconCount);
TraceLog.Stat("FriendCacheOp.OnStop error, ErrIconCount {0}", cache.ErrIconCount);
}
}
public static bool IsAllDataSave()
{
return FriendInfoCache.m_selfIDMap.Count == 0;
}
public static void SendDBSaveFriendListReq(ref FriendCacheInfoStruct infoStruct, bool newInsert)
{
SSSaveFriendListReq req = new SSSaveFriendListReq();
FriendOp.TransFriendCacheInfoStruct(ref infoStruct, ref req.Self, ref req.List, ref req.OpData);
req.Uid = infoStruct.Self.Uid;
req.DataSeq = infoStruct.GetDataSeqSave().DataSeq;
req.NewInsert = newInsert;
infoStruct.GetDataSeqSave().OnSaveReq(FriendServerUtils.GetTimeMs());
uint dbServerID = FriendSvrIDUtils.GetDBServerID(infoStruct.Self.Uid);
FriendServerUtils.GetPacketSender().SendToServerByID(dbServerID, (int)SSGameMsgID.SaveFriendListReq, ref req, infoStruct.Self.Uid);
}
public static void SendDBOrFriendSvrQueryFriendInfo(long uid, long fromUid, QueryFriendInfoCacheReason reason)
{
// 玩家属于当前服务器, 转给DB查询, 否则转给目标friendSvr处理
if (FriendUtils.IsPlayerBelongThisServer(uid))
{
SendDBQueryFriendInfoCache(uid, fromUid, reason);
}
else
{
SendFriendSvrQueryFriendInfoCache(uid, fromUid, reason);
}
}
public static void SendDBQueryFriendInfoCache(long uid, long fromUid, QueryFriendInfoCacheReason reason)
{
MakeQueryFriendInfoCacheReq(uid, fromUid, reason);
uint dbServerID = FriendSvrIDUtils.GetDBServerID(uid);
FriendServerUtils.GetPacketSender().SendToServerByID(dbServerID, (int)SSGameMsgID.QueryFriendInfoCacheReq,
ref m_SSQueryFriendInfoCacheReq, uid, FriendServerUtils.GetAppID());
}
public static void SendFriendSvrQueryFriendInfoCache(long uid, long fromUid, QueryFriendInfoCacheReason reason)
{
MakeQueryFriendInfoCacheReq(uid, fromUid, reason);
// 转给玩家所在FriendSvr
FriendServerUtils.GetPacketSender().SendToFriendServer((int)SSGameMsgID.QueryFriendInfoCacheReq,
ref m_SSQueryFriendInfoCacheReq, uid, FriendServerUtils.GetAppID());
}
public static void SendDBQueryFriendInfoCacheOnFriendOp(long submit, int opType, long target, QueryFriendInfoCacheReason reason)
{
MakeQueryFriendInfoCacheReq(submit, opType, target, reason);
uint dbServerID = FriendSvrIDUtils.GetDBServerID(target);
FriendServerUtils.GetPacketSender().SendToServerByID(dbServerID, (int)SSGameMsgID.QueryFriendInfoCacheReq,
ref m_SSQueryFriendInfoCacheReq, target, FriendServerUtils.GetAppID());
}
public static void SendDBQueryFriendInfoCacheBySaveChat(long uid, long fromUid, ref CSChatRes chatRes)
{
MakeQueryFriendInfoCacheReq(uid, fromUid, QueryFriendInfoCacheReason.SaveChat);
m_SSQueryFriendInfoCacheReq.ChatRes = chatRes;
uint dbServerID = FriendSvrIDUtils.GetDBServerID(uid);
FriendServerUtils.GetPacketSender().SendToServerByID(dbServerID, (int)SSGameMsgID.QueryFriendInfoCacheReq,
ref m_SSQueryFriendInfoCacheReq, uid, FriendServerUtils.GetAppID());
}
public static void SendDBQueryFriendInfoCacheByQueryChat(long uid, long fromUid, long seq)
{
MakeQueryFriendInfoCacheReq(uid, fromUid, QueryFriendInfoCacheReason.QueryChat);
m_SSQueryFriendInfoCacheReq.ChatSeq = seq;
uint dbServerID = FriendSvrIDUtils.GetDBServerID(uid);
FriendServerUtils.GetPacketSender().SendToServerByID(dbServerID, (int)SSGameMsgID.QueryFriendInfoCacheReq,
ref m_SSQueryFriendInfoCacheReq, uid, FriendServerUtils.GetAppID());
}
private static void MakeQueryFriendInfoCacheReq(long uid, long fromUid, QueryFriendInfoCacheReason reason)
{
m_SSQueryFriendInfoCacheReq.Clear();
m_SSQueryFriendInfoCacheReq.FromUid = fromUid; //查找发起者
m_SSQueryFriendInfoCacheReq.Uid = uid; //被查找者
m_SSQueryFriendInfoCacheReq.Reason = reason;
}
private static void MakeQueryFriendInfoCacheReq(long submit, int opType, long target, QueryFriendInfoCacheReason reason)
{
m_SSQueryFriendInfoCacheReq.Clear();
m_SSQueryFriendInfoCacheReq.FromUid = submit;
m_SSQueryFriendInfoCacheReq.Uid = target;
m_SSQueryFriendInfoCacheReq.Reason = reason;
m_SSQueryFriendInfoCacheReq.OpCallback.SubmitUid = submit;
m_SSQueryFriendInfoCacheReq.OpCallback.OpType = opType;
m_SSQueryFriendInfoCacheReq.OpCallback.TargetUid = target;
}
// 收到其他friendsvr发来的查询请求
public static void OnQueryFriendInfoCacheReqFromOtherFriendSvr(uint remoteAppID, StructPacket packet)
{
ref SSQueryFriendInfoCacheReq req = ref packet.GetMessage<SSQueryFriendInfoCacheReq>();
// 这2种情况都是直接发给DB的, 不应该收到其他friendSvr发过来
if (req.Reason == QueryFriendInfoCacheReason.QueryByCliOp
|| req.Reason == QueryFriendInfoCacheReason.QueryBySsOp)
{
TraceLog.Error("FriendCacheSvc.OnQueryFriendInfoCacheReqFromOtherFriendSvr QueryByCliOp must send to DB, uid {0}", req.Uid);
return;
}
// 不是这个服的玩家为什么发过来, 不转发请求, 打日志查下bug
if (! FriendUtils.IsPlayerBelongThisServer(req.Uid))
{
TraceLog.Error("FriendCacheSvc.OnQueryFriendInfoCacheReqFromOtherFriendSvr uid {0} not belong this svr",
req.Uid);
return;
}
ref FriendCacheInfoStruct cacheInfo = ref FriendOp.GetFriendInfoByUid(req.Uid);
if (cacheInfo.IsNull())
{
TraceLog.Trace("FriendCacheSvc.OnQueryFriendInfoCacheReqFromOtherFriendSvr uid {0} FriendCacheInfo not cache"
, req.Uid);
SendDBQueryFriendInfoCache(req.Uid, req.FromUid, req.Reason);
return;
}
m_SSQueryFriendInfoCacheRes.Uid = req.Uid;
m_SSQueryFriendInfoCacheRes.FromUid = req.FromUid;
m_SSQueryFriendInfoCacheRes.Reason = req.Reason;
m_SSQueryFriendInfoCacheRes.OpCallback = req.OpCallback;
m_SSQueryFriendInfoCacheRes.List.Clear();
m_SSQueryFriendInfoCacheRes.OpData.Clear();
m_SSQueryFriendInfoCacheRes.Self = cacheInfo.Self;
FriendServerUtils.GetPacketSender().SendToServerByID(remoteAppID,
(int)SSGameMsgID.QueryFriendInfoCacheRes, ref m_SSQueryFriendInfoCacheRes, req.Uid);
}
public static void OnQueryFriendInfoCacheResFromDB(uint remoteAppID, StructPacket packet)
{
ref SSQueryFriendInfoCacheRes res = ref packet.GetMessage<SSQueryFriendInfoCacheRes>();
TraceLog.Trace("FriendCacheSvc.OnQueryFriendInfoCacheResFromDB uid {0} fromUid {1} reason {2} DB.Uid {3}"
, res.Uid, res.FromUid, res.Reason, res.Self.Uid);
if (res.Self.Uid != 0)
{
if (FriendUtils.IsPlayerBelongThisServer(res.Self.Uid))
{
// 取最新的在线状态
//res.Self.IsOnline = FriendServerUtils.GetFriendServerData().m_playerOnline.Contains(res.Self.Uid);
ref FriendCacheInfoStruct info = ref FriendOp.GetFriendInfoByUid(res.Uid);
if (info.IsNull())
{
FriendOp.AddFriendCacheInfoStruct(ref res.Self, ref res.List, ref res.OpData);
}
}
else
{
FriendOp.AddOrUpdateRemoteFriendOne(ref res.Self);
}
}
//登录拉取好友列表里的玩家的数据
if (res.Reason == QueryFriendInfoCacheReason.LoginQuerySnsFriend
|| res.Reason == QueryFriendInfoCacheReason.LoginQueryDBFriend
|| res.Reason == QueryFriendInfoCacheReason.QueryFriendOneStruct
|| res.Reason == QueryFriendInfoCacheReason.QueryBlacklist)
{
FriendSnsSvc.OnQueryFriendInfoCacheResFromDB(ref res);
return;
}
// 操作双方同服
if (res.Reason == QueryFriendInfoCacheReason.QueryByCliOp)
{
FriendOpSvc.DoFriendOpOnBothDataLoad(ref res);
return;
}
// 操作双方不同服, 处理target后通知另一个friendsvr处理submit
if (res.Reason == QueryFriendInfoCacheReason.QueryBySsOp)
{
FriendOpSvc.DoFriendOpTargetSideFirst(ref res);
return;
}
// 赠送
if (res.Reason == QueryFriendInfoCacheReason.QueryBySendGift)
{
FriendSvc.DoFriendSendGiftOnDataLoad(res.Uid, res.FromUid);
return;
}
// 写入私聊
if (res.Reason == QueryFriendInfoCacheReason.SaveChat && res.Self.Uid != 0)
{
ChatSvc.SavePrivateChatOnDBRes(ref res.ChatRes);
return;
}
// 拉取私聊
if (res.Reason == QueryFriendInfoCacheReason.QueryChat && res.Self.Uid != 0)
{
ChatSvc.OnQueryChatDataResFromDB(res.Uid, res.ChatSeq);
return;
}
// 根据uid查询玩家信息
if (res.Reason == QueryFriendInfoCacheReason.QueryByUid)
{
FriendRecommenderSvc.OnQueryFriendInfoCacheResFromDB(ref res);
return;
}
}
//收到其他FriendSvr通知friendUid更新好友列表中selfUid的基本信息
public static void OnFriendSelfChgFromOtherSvr(uint remoteAppID, StructPacket packet)
{
ref SSFriendSelfChgNotify notify = ref packet.GetMessage<SSFriendSelfChgNotify>();
TraceLog.Trace("FriendCacheSvc.OnFriendSelfChgFromOtherSvr selfUid {0}", notify.Self.Uid);
// 当前服务器管理的玩家却收到其他服务器发来的通知
if (FriendUtils.IsPlayerBelongThisServer(notify.Self.Uid))
{
TraceLog.Error("FriendCacheSvc.OnFriendSelfChgFromOtherSvr uid {0} must in this svr", notify.Self.Uid);
return;
}
// 更新缓存池中的数据, 缓存池中有才更新, 没有说明暂时不需要该玩家数据, 不用新增, 降低内存占用
ref RemoteFriendOneStruct remoteFriend = ref FriendOp.GetRemoteFriendOneByUid(notify.Self.Uid);
if (! remoteFriend.IsNull())
{
FriendUtils.CopySelfToRemoteFriend(ref notify.Self, ref remoteFriend);
}
}
public static ref DBFriendOneStruct UpdateFriendInfoToInFriendList(
ref FriendCacheInfoStruct friendCache, ref DBFriendSelf self)
{
for (int i = 0; i < friendCache.FriendList.iCount; i++)
{
ref DBFriendOneStruct one = ref FriendOp.GetFriendOneByIndex(ref friendCache, i);
if (one.oneFriend.Uid == self.Uid)
{
FriendOp.UpdateSelfInfoTOFriendOne(ref self, ref one);
return ref one;
}
}
return ref FriendInfoCache.m_cacheStructFriendOne.GetByIndex(0);
}
}
}