using System; using System.Collections.Generic; using System.ComponentModel.Design; using System.Linq; using System.Threading.Tasks; using Sog; using ProtoCSStruct; namespace Friend { /// /// 好友数据的内存cache /// 处理逻辑是如果需要处理好友数据,那么先把数据拉取到内存,这样写起逻辑来比较简单,处理完后如果一段时间内不再访问,则淘汰 /// 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(); // 这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(); 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(); 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); } } }