diff --git a/server/imserver/app.cc b/server/imserver/app.cc index 4152783..2d0e33d 100644 --- a/server/imserver/app.cc +++ b/server/imserver/app.cc @@ -28,6 +28,7 @@ #include "asynctaskmgr.h" #include "guildmgr.h" #include "metamgr.h" +#include "chatmgr.h" #include "MSConnMgr.h" #include "IMConnMgr.h" @@ -112,6 +113,7 @@ bool App::Init(int argc, char* argv[]) SyncHelper::Instance()->Init(); AsyncTaskMgr::Instance()->Init(); GuildMgr::Instance()->Init(); + ChatMgr::Instance()->Init(); a8::UdpLog::Instance()->Info("friend_imserver starting instance_id:%d pid:%d 13423", { @@ -146,6 +148,7 @@ bool App::Init(int argc, char* argv[]) void App::UnInit() { a8::XPrintf("friend_imserver terminating instance_id:%d pid:%d\n", {instance_id, getpid()}); + ChatMgr::Instance()->UnInit(); GuildMgr::Instance()->UnInit(); AsyncTaskMgr::Instance()->UnInit(); SyncHelper::Instance()->UnInit(); diff --git a/server/imserver/chatmgr.cc b/server/imserver/chatmgr.cc new file mode 100644 index 0000000..c230593 --- /dev/null +++ b/server/imserver/chatmgr.cc @@ -0,0 +1,156 @@ +#include "precompile.h" + +#include "chatmgr.h" +#include "player.h" +#include "playermgr.h" +#include "guild.h" +#include "guildmgr.h" + +void ChatMgr::Init() +{ + +} + +void ChatMgr::UnInit() +{ + +} + +void ChatMgr::FillSMUpdateChatRedPointNotify(Player* hum, cs::SMUpdateChatRedPointNotify& msg) +{ + if (world_msgrec_.curr_id > hum->world_channel_last_id) { + msg.add_has_unread_msg_channels(kCCWorld); + } + if (hum->GuildId() != 0) { + auto itr = guild_msgrec_.find(hum->GuildId()); + if (itr != guild_msgrec_.end()) { + if (itr->second.curr_id > hum->guild_channel_last_id) { + msg.add_has_unread_msg_channels(kCCGuild); + } + } + } + ChatedUserRec* chated_user = GetChatedUser(hum->AccountId()); + if (chated_user && chated_user->has_unread_msg) { + msg.add_has_unread_msg_channels(kCCPrivate); + } +} + +void ChatMgr::FillSMUpdatePrivateChatRedPointNotify(Player* hum, + cs::SMUpdatePrivateChatRedPointNotify& msg) +{ + ChatedUserRec* chated_user = GetChatedUser(hum->AccountId()); + if (chated_user) { + for (auto& pair : chated_user->users) { + if (pair.second.curr_id < pair.second.last_id) { + msg.add_has_unread_msg_accounts(pair.first); + } + } + } +} + +void ChatMgr::ProcWorldChat(Player* hum, const cs::CMSendChatMsg& msg) +{ + ++world_msg_id_; + + cs::MFChatMsg* p = new cs::MFChatMsg(); + p->set_msg_uuid(world_msg_id_); + + world_msgrec_.curr_id = world_msg_id_; + world_msgrec_.msg_list.push_back(p); + world_msgrec_.PopAndDelete(50); + PlayerMgr::Instance()->TraversePlayer + ([](Player* hum) + { + ChatMgr::Instance()->SyncWorldChatMsg(hum); + }); +} + +void ChatMgr::ProcPrivateChat(Player* hum, const cs::CMSendChatMsg& msg) +{ + ++private_msg_id_; + + cs::MFChatMsg* p = new cs::MFChatMsg(); + p->set_msg_uuid(private_msg_id_); + + ChatMgr::Instance()->SyncPrivateChatMsg(hum); + Player* target_hum = PlayerMgr::Instance()->GetPlayerByAccountId(msg.target()); + if (target_hum) { + ChatMgr::Instance()->SyncPrivateChatMsg(target_hum); + } +} + +void ChatMgr::ProcGuildChat(Player* hum, const cs::CMSendChatMsg& msg) +{ + ++guild_msg_id_; + + cs::MFChatMsg* p = new cs::MFChatMsg(); + p->set_msg_uuid(guild_msg_id_); + + Guild* guild = GuildMgr::Instance()->GetGuild(hum->GuildId()); + if (guild) { + guild->TraverseMember + ( + [] (GuildMember* member) + { + Player* hum = PlayerMgr::Instance()->GetPlayerByAccountId(member->account_id); + if (hum) { + ChatMgr::Instance()->SyncGuildChatMsg(hum); + } + } + ); + } +} + +ChatedUserRec* ChatMgr::GetChatedUser(const std::string& account_id) +{ + auto itr = private_chated_users_.find(account_id); + return itr != private_chated_users_.end() ? &itr->second : nullptr; +} + +void ChatMgr::SyncWorldChatMsg(Player* hum) +{ + if (hum->chat_channel == kCCWorld) { + cs::SMChatMsgNotify notifymsg; + for (cs::MFChatMsg* chat_msg : world_msgrec_.msg_list) { + if (chat_msg->msg_uuid() > hum->world_channel_last_id) { + *notifymsg.add_msg_list() = *chat_msg; + hum->world_channel_last_id = chat_msg->msg_uuid(); + } + } + if (!notifymsg.msg_list().size() > 0) { + hum->SendMsg(notifymsg); + } + } else { + hum->MarkNewMsg(); + } + +} + +void ChatMgr::SyncPrivateChatMsg(Player* hum) +{ + +} + +void ChatMgr::SyncGuildChatMsg(Player* hum) +{ + if (hum->GuildId() == 0) { + return; + } + auto itr = guild_msgrec_.find(hum->GuildId()); + if (itr != guild_msgrec_.end()) { + if (hum->chat_channel == kCCGuild) { + cs::SMChatMsgNotify notifymsg; + for (cs::MFChatMsg* chat_msg : world_msgrec_.msg_list) { + if (chat_msg->msg_uuid() > hum->guild_channel_last_id) { + *notifymsg.add_msg_list() = *chat_msg; + hum->guild_channel_last_id = chat_msg->msg_uuid(); + } + } + if (!notifymsg.msg_list().size() > 0) { + hum->SendMsg(notifymsg); + } + } else { + hum->MarkNewMsg(); + } + } +} diff --git a/server/imserver/chatmgr.h b/server/imserver/chatmgr.h new file mode 100644 index 0000000..6573a03 --- /dev/null +++ b/server/imserver/chatmgr.h @@ -0,0 +1,62 @@ +#pragma once + +#include "cs_proto.pb.h" + +struct ChatMsgRec +{ + + long long curr_id = 0; + long long last_id = 0; + std::list msg_list; + + void Pop(int max_num) + { + + } + + void PopAndDelete(int max_num) + { + + } + +}; + +struct ChatedUserRec +{ + bool has_unread_msg = false; + std::map users; +}; + +class Player; +class ChatMgr : public a8::Singleton +{ + private: + ChatMgr() {}; + friend class a8::Singleton; + + public: + void Init(); + void UnInit(); + + void FillSMUpdateChatRedPointNotify(Player* hum, cs::SMUpdateChatRedPointNotify& msg); + void FillSMUpdatePrivateChatRedPointNotify(Player* hum, cs::SMUpdatePrivateChatRedPointNotify& msg); + + void ProcWorldChat(Player* hum, const cs::CMSendChatMsg& msg); + void ProcPrivateChat(Player* hum, const cs::CMSendChatMsg& msg); + void ProcGuildChat(Player* hum, const cs::CMSendChatMsg& msg); + + private: + ChatedUserRec* GetChatedUser(const std::string& account_id); + void SyncWorldChatMsg(Player* hum); + void SyncPrivateChatMsg(Player* hum); + void SyncGuildChatMsg(Player* hum); + + private: + long long private_msg_id_ = 1000; + long long world_msg_id_ = 1000; + long long guild_msg_id_ = 1000; + ChatMsgRec world_msgrec_; + std::map guild_msgrec_; + std::map private_msg_hash_; + std::map private_chated_users_; +}; diff --git a/server/imserver/constant.h b/server/imserver/constant.h index 9914565..db79099 100644 --- a/server/imserver/constant.h +++ b/server/imserver/constant.h @@ -77,9 +77,9 @@ enum GuildMemberUpdateReason enum ChatChannel_e { - kCCWorld = 0, - kCCFriend = 1, - kCCGuild = 2 + kCCWorld = 1, + kCCPrivate = 2, + kCCGuild = 3 }; const char* const PROJ_NAME_FMT = "friend_imserver"; diff --git a/server/imserver/guild.cc b/server/imserver/guild.cc index 083eb2e..b6a18d3 100644 --- a/server/imserver/guild.cc +++ b/server/imserver/guild.cc @@ -1145,6 +1145,13 @@ void Guild::SyncNewApply() } } +void Guild::TraverseMember(std::function callback) +{ + for (auto& pair : member_hash_) { + callback(pair.second); + } +} + int Guild::GetJobMemberNum(int job) { std::set* members = GetJobMembers(job); diff --git a/server/imserver/guild.h b/server/imserver/guild.h index a110a04..73e66f2 100644 --- a/server/imserver/guild.h +++ b/server/imserver/guild.h @@ -48,6 +48,7 @@ public: bool CheckRedPoint(); bool HasApply(); void SyncNewApply(); + void TraverseMember(std::function callback); private: bool IsFull(); diff --git a/server/imserver/handlermgr.cc b/server/imserver/handlermgr.cc index c378bea..b718a46 100644 --- a/server/imserver/handlermgr.cc +++ b/server/imserver/handlermgr.cc @@ -103,6 +103,7 @@ void HandlerMgr::RegisterNetMsgHandlers() RegisterNetMsgHandler(&wsmsghandler, &Player::_CMSendChatMsg); RegisterNetMsgHandler(&wsmsghandler, &Player::_CMReadMsgAndOpenChatNotify); + RegisterNetMsgHandler(&wsmsghandler, &Player::_CMSetCurrPrivateChatTarget); RegisterNetMsgHandler(&wsmsghandler, &Player::_CMCloseChatNotify); RegisterNetMsgHandler(&wsmsghandler, &Player::_CMSendCustomMsg); RegisterNetMsgHandler(&wsmsghandler, &Player::_CMDirtyWordCheck); diff --git a/server/imserver/player.cc b/server/imserver/player.cc index bee0d8f..40e3b24 100644 --- a/server/imserver/player.cc +++ b/server/imserver/player.cc @@ -26,6 +26,7 @@ #include "MSConnMgr.h" #include "handlermgr.h" #include "jsondatamgr.h" +#include "chatmgr.h" #include "ss_msgid.pb.h" #include "framework/cpp/httpclientpool.h" @@ -79,6 +80,20 @@ void Player::Init() }, &timer_attacher.timer_list_ ); + a8::Timer::Instance()->AddDeadLineTimerAndAttach + ( + 1000 * 2 + (rand() % 3000), + a8::XParams() + .SetSender(this), + [] (const a8::XParams& param) + { + Player* hum = (Player*)param.sender.GetUserData(); + cs::SMUpdateChatRedPointNotify msg; + ChatMgr::Instance()->FillSMUpdateChatRedPointNotify(hum, msg); + hum->SendMsg(msg); + }, + &timer_attacher.timer_list_ + ); } void Player::UnInit() @@ -548,6 +563,22 @@ void Player::_CMFriendIdList(f8::MsgHdr& hdr, const cs::CMFriendIdList& msg) void Player::_CMSendChatMsg(f8::MsgHdr& hdr, const cs::CMSendChatMsg& msg) { + if (!IsValidChatChannel(msg.chat_channel())) { + return; + } + switch (msg.chat_channel()) { + case kCCWorld: + ChatMgr::Instance()->ProcWorldChat(this, msg); + break; + case kCCPrivate: + ChatMgr::Instance()->ProcPrivateChat(this, msg); + break; + case kCCGuild: + ChatMgr::Instance()->ProcGuildChat(this, msg); + break; + default: + return; + } ss::SS_IM_SendChatMsg ss_msg; FillIMMsgConext(ss_msg.mutable_context()); ss_msg.set_chat_channel(msg.chat_channel()); @@ -563,18 +594,28 @@ void Player::_CMSendChatMsg(f8::MsgHdr& hdr, const cs::CMSendChatMsg& msg) void Player::_CMReadMsgAndOpenChatNotify(f8::MsgHdr& hdr, const cs::CMReadMsgAndOpenChatNotify& msg) { if (IsValidChatChannel(msg.curr_channel())) { - chat_channel_ = msg.curr_channel(); - } - for (auto& pair : msg.last_ids()) { - if (IsValidChatChannel(pair.key())) { - chat_last_ids_hash_[pair.key()] = pair.val(); + chat_channel = msg.curr_channel(); + if (chat_channel == kCCPrivate) { + SyncPrivateChatRedPoint(); + } + + for (auto& pair : msg.last_ids()) { + if (IsValidChatChannel(pair.key())) { + chat_last_ids_hash[pair.key()] = pair.val(); + } } } } +void Player::_CMSetCurrPrivateChatTarget(f8::MsgHdr& hdr, const cs::CMSetCurrPrivateChatTarget& msg) +{ + private_target = msg.private_target(); +} + void Player::_CMCloseChatNotify(f8::MsgHdr& hdr, const cs::CMCloseChatNotify& msg) { - chat_channel_ = -1; + chat_channel = -1; + private_target = ""; } void Player::_CMSendCustomMsg(f8::MsgHdr& hdr, const cs::CMSendCustomMsg& msg) @@ -1473,6 +1514,11 @@ void Player::SaveToDB(a8::XParams param, f8::AsyncDBOnOkFunc on_ok, f8::AsyncDBO role_data.last_save_time = App::Instance()->nowtime; } +void Player::MarkNewMsg() +{ + +} + Friend* Player::GetFriendById(const std::string& friend_id) { auto itr = friend_hash_.find(friend_id); @@ -2272,9 +2318,15 @@ void Player::SyncGuildNewApply(long long guild_id) bool Player::IsValidChatChannel(int chat_channel) { - if (chat_channel >= 0 && chat_channel < 2) { + if (chat_channel >= kCCWorld && chat_channel <= kCCGuild) { return true; } else { return false; } } + +void Player::SyncPrivateChatRedPoint() +{ + cs::SMUpdatePrivateChatRedPointNotify msg; + ChatMgr::Instance()->FillSMUpdatePrivateChatRedPointNotify(this, msg); +} diff --git a/server/imserver/player.h b/server/imserver/player.h index f9909dc..1c3059c 100644 --- a/server/imserver/player.h +++ b/server/imserver/player.h @@ -24,6 +24,13 @@ class Player long ip_saddr = 0; int account_registertime = 0; + int chat_channel = -1; + std::string private_target; + std::map chat_last_ids_hash; + + long long world_channel_last_id = 0; + long long guild_channel_last_id = 0; + public: void Init(); void UnInit(); @@ -95,6 +102,7 @@ class Player void _CMSendChatMsg(f8::MsgHdr& hdr, const cs::CMSendChatMsg& msg); void _CMReadMsgAndOpenChatNotify(f8::MsgHdr& hdr, const cs::CMReadMsgAndOpenChatNotify& msg); + void _CMSetCurrPrivateChatTarget(f8::MsgHdr& hdr, const cs::CMSetCurrPrivateChatTarget& msg); void _CMCloseChatNotify(f8::MsgHdr& hdr, const cs::CMCloseChatNotify& msg); void _CMSendCustomMsg(f8::MsgHdr& hdr, const cs::CMSendCustomMsg& msg); void _CMDirtyWordCheck(f8::MsgHdr& hdr, const cs::CMDirtyWordCheck& msg); @@ -156,6 +164,7 @@ class Player int GetFriendNum(); void SaveToDB(a8::XParams param, f8::AsyncDBOnOkFunc on_ok, f8::AsyncDBOnErrorFunc on_error); + void MarkNewMsg(); private: void FillFriendList(::google::protobuf::RepeatedPtrField< ::cs::MFUserInfo >* friend_list); @@ -200,6 +209,7 @@ private: void SyncGuildRedPoint(); void SyncGuildNewApply(long long guild_id); bool IsValidChatChannel(int chat_channel); + void SyncPrivateChatRedPoint(); private: bool dirty_ = false; @@ -215,8 +225,6 @@ private: std::set exclude_account_ids_; std::string user_sign_; int last_create_guild_time_ = 0; - int chat_channel_ = -1; - std::map chat_last_ids_hash_; std::map friend_hash_; std::map black_hash_; diff --git a/server/imserver/playermgr.cc b/server/imserver/playermgr.cc index fea4465..aef43a4 100644 --- a/server/imserver/playermgr.cc +++ b/server/imserver/playermgr.cc @@ -37,16 +37,16 @@ void PlayerMgr::_SS_MS_PushUserList(f8::MsgHdr& hdr, const ss::SS_MS_PushUserLis void PlayerMgr::_SS_IM_SendChatMsg(f8::MsgHdr& hdr, const ss::SS_IM_SendChatMsg& msg) { - #if 0 Player* hum = GetPlayerByAccountId(msg.target()); if (hum) { + #if 0 cs::SMChatMsgNotify notifymsg; notifymsg.set_sender(msg.context().user_info().base_data().account_id()); notifymsg.set_chat_channel(msg.chat_channel()); notifymsg.set_msg(msg.msg()); hum->SendMsg(notifymsg); + #endif } - #endif } void PlayerMgr::_SS_IM_SendCustomMsg(f8::MsgHdr& hdr, const ss::SS_IM_SendCustomMsg& msg) @@ -353,6 +353,13 @@ void PlayerMgr::Update(long long tick) } } +void PlayerMgr::TraversePlayer(std::function callback) +{ + for (auto& pair : accountid_hash_) { + callback(pair.second); + } +} + Player* PlayerMgr::GetPlayerBySocket(int socket) { auto itr = socket_hash_.find(socket); diff --git a/server/imserver/playermgr.h b/server/imserver/playermgr.h index c178390..1f42bcb 100644 --- a/server/imserver/playermgr.h +++ b/server/imserver/playermgr.h @@ -81,6 +81,7 @@ class PlayerMgr : public a8::Singleton int OnlineNum(); int WatchPlayerNum(); void Update(long long tick); + void TraversePlayer(std::function callback); private: void OnClientDisconnect(a8::XParams& param);