From 8f2a129f4b70c824b04e52ecef19d92764c5d6a2 Mon Sep 17 00:00:00 2001 From: azw Date: Sun, 19 Feb 2023 06:43:00 +0000 Subject: [PATCH] 1 --- server/imserver/chatmgr.cc | 419 +++++++++++++++++++++++++++++++++++++ server/imserver/chatmgr.h | 63 ++++++ server/imserver/player.h | 4 +- 3 files changed, 485 insertions(+), 1 deletion(-) create mode 100644 server/imserver/chatmgr.cc create mode 100644 server/imserver/chatmgr.h diff --git a/server/imserver/chatmgr.cc b/server/imserver/chatmgr.cc new file mode 100644 index 0000000..ec8784a --- /dev/null +++ b/server/imserver/chatmgr.cc @@ -0,0 +1,419 @@ +#include "precompile.h" + +#include + +#include "chatmgr.h" +#include "player.h" +#include "playermgr.h" + +struct ChatedUserRec +{ + bool has_unread_msg = false; + bool dirty = false; + std::map users; +}; + +ChatMsgRec::~ChatMsgRec() +{ + for (cs::MFChatMsg* msg : msg_list) { + delete msg; + } + msg_list.clear(); +} + +void ChatMsgRec::Pop(size_t max_num) +{ + while (msg_list.size() > max_num) { + msg_list.erase(msg_list.begin()); + } +} + +void ChatMsgRec::PopAndDelete(size_t max_num) +{ + while (msg_list.size() > max_num) { + cs::MFChatMsg* msg = *msg_list.begin(); + msg_list.erase(msg_list.begin()); + delete msg; + } +} + +void ChatMgr::Init() +{ + world_msg_id_ = a8::GetMilliSecond(); + guild_msg_id_ = a8::GetMilliSecond(); + temp_msg_id_ = a8::GetMilliSecond(); +} + +void ChatMgr::UnInit() +{ + +} + +void ChatMgr::FillSMUpdateChatRedPointNotify(Player* hum, cs::SMUpdateChatRedPointNotify& msg) +{ + #if 0 + 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) { + if (chated_user->dirty) { + chated_user->has_unread_msg = false; + chated_user->dirty = false; + } + if (chated_user->has_unread_msg) { + msg.add_has_unread_msg_channels(kCCPrivate); + } + } + #endif +} + +void ChatMgr::FillSMUpdatePrivateChatRedPointNotify(Player* hum, + cs::SMUpdatePrivateChatRedPointNotify& msg) +{ + #if 0 + 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); + } + } + } + #endif +} + +void ChatMgr::ProcWorldChat(Player* hum, const cs::CMSendChatMsg& msg) +{ + cs::MFChatMsg* p = new cs::MFChatMsg(); + FillMFChatMsg(p, hum, ++world_msg_id_, msg.chat_channel(), msg.msg_type(), msg.msg_body()); + + world_msgrec_.curr_id = world_msg_id_; + world_msgrec_.msg_list.push_back(p); + world_msgrec_.PopAndDelete(50); + #if 0 + PlayerMgr::Instance()->TraversePlayer + ([](Player* hum) + { + ChatMgr::Instance()->SyncWorldChatMsg(hum); + }); + #endif +} + +void ChatMgr::ProcPrivateChat(Player* hum, const cs::CMSendChatMsg& msg) +{ + if (hum->AccountId() == msg.target()) { + return; + } + #if 0 + Friend* target = hum->GetFriendById(msg.target()); + if (!target) { + return; + } + cs::MFChatMsg* p = new cs::MFChatMsg(); + FillMFChatMsg(p, hum, 0, msg.chat_channel(), msg.msg_type(), msg.msg_body()); + { + TypeConvert::Convert(target->base_data, *p->mutable_receiver()->mutable_base_data()); + TypeConvert::Convert(target->temp_custom_data, *p->mutable_receiver()->mutable_temp_custom_data()); + } + + AddChatedUser(hum->AccountId(), msg.target(), p, hum->IncDBPrivateChatLastId()); + ChatMgr::Instance()->SyncPrivateChatMsg(hum); + Player* target_hum = PlayerMgr::Instance()->GetPlayerByAccountId(msg.target()); + if (target_hum) { + ChatMgr::Instance()->SyncPrivateChatMsg(target_hum); + AddChatedUser(msg.target(), hum->AccountId(), p, target_hum->IncDBPrivateChatLastId()); + } else { + AddChatedUser(msg.target(), hum->AccountId(), p, 0); + } + #endif +} + +void ChatMgr::ProcGuildChat(Player* hum, const cs::CMSendChatMsg& msg) +{ + #if 0 + if (hum->GuildId() == 0) { + return; + } + cs::MFChatMsg* p = new cs::MFChatMsg(); + FillMFChatMsg(p, hum, ++guild_msg_id_, msg.chat_channel(), msg.msg_type(), msg.msg_body()); + + auto itr = guild_msgrec_.find(hum->GuildId()); + if (itr != guild_msgrec_.end()) { + itr->second.msg_list.push_back(p); + itr->second.PopAndDelete(50); + } else { + ChatMsgRec msgrec; + msgrec.curr_id = guild_msg_id_; + guild_msgrec_[hum->GuildId()] = msgrec; + } + #if 0 + 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); + } + } + ); + } + #endif + #endif +} + +void ChatMgr::ProcTeamChat(Player* hum, const cs::CMSendChatMsg& msg) +{ + cs::MFChatMsg* p = new cs::MFChatMsg(); + FillMFChatMsg(p, hum, ++temp_msg_id_, msg.chat_channel(), msg.msg_type(), msg.msg_body()); + + cs::SMChatMsgNotify notifymsg; + *notifymsg.add_msg_list() = *p; + for (auto& member_id : msg.members()) { + #if 0 + Player* hum = PlayerMgr::Instance()->GetPlayerByAccountId(member_id); + if (hum) { + hum->SendMsg(notifymsg); + if (hum->chat_channel == kCCTeam) { + a8::SetBitFlag(hum->red_point_flags_, RPF_Chat); + hum->SyncRedPoint(); + } + } + #endif + } + delete p; +} + +void ChatMgr::ProcBigHornChat(Player* hum, const cs::CMSendChatMsg& msg) +{ + cs::MFChatMsg* p = new cs::MFChatMsg(); + FillMFChatMsg(p, hum, ++temp_msg_id_, msg.chat_channel(), msg.msg_type(), msg.msg_body()); + + cs::SMChatMsgNotify notifymsg; + *notifymsg.add_msg_list() = *p; + #if 0 + PlayerMgr::Instance()->TraversePlayer + ([¬ifymsg](Player* hum) + { + hum->SendMsg(notifymsg); + }); + #endif + + #if 0 + { + p->set_msg_uuid(++world_msg_id_); + p->set_chat_channel(kCCWorld); + 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); + }); + } + #endif +} + +void ChatMgr::ProcLoopMsgChat(Player* hum, const cs::CMSendChatMsg& msg) +{ + cs::MFChatMsg* p = new cs::MFChatMsg(); + FillMFChatMsg(p, hum, ++temp_msg_id_, msg.chat_channel(), msg.msg_type(), msg.msg_body()); + + cs::SMChatMsgNotify notifymsg; + *notifymsg.add_msg_list() = *p; + #if 0 + PlayerMgr::Instance()->TraversePlayer + ([¬ifymsg](Player* hum) + { + hum->SendMsg(notifymsg); + }); + #endif + delete p; +} + +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 0 + 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(); + } + #endif +} + +void ChatMgr::SyncPrivateChatMsg(Player* hum) +{ + #if 0 + if (hum->chat_channel == kCCPrivate) { + ChatedUserRec* chated_user = GetChatedUser(hum->AccountId()); + if (chated_user) { + cs::SMChatMsgNotify notifymsg; + auto itr = chated_user->users.find(hum->private_target); + if (itr != chated_user->users.end()) { + for (cs::MFChatMsg* chat_msg : itr->second.msg_list) { + if (chat_msg->msg_uuid() > itr->second.curr_id) { + *notifymsg.add_msg_list() = *chat_msg; + itr->second.curr_id = chat_msg->msg_uuid(); + chated_user->dirty = true; + } + } + } + if (notifymsg.msg_list().size() > 0) { + hum->SendMsg(notifymsg); + } + } + } else { + hum->MarkNewMsg(); + a8::SetBitFlag(hum->red_point_flags_, RPF_Chat); + hum->SyncRedPoint(); + } + #endif +} + +void ChatMgr::SyncGuildChatMsg(Player* hum) +{ + #if 0 + 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 : itr->second.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(); + a8::SetBitFlag(hum->red_point_flags_, RPF_Chat); + hum->SyncRedPoint(); + } + } + #endif +} + +void ChatMgr::OnPlayerOnline(Player* hum) +{ + ChatedUserRec* user = GetChatedUser(hum->AccountId()); + if (user) { + #if 0 + long long init_last_id = hum->GetDBPrivateChatLastId(); + for (auto& pair : user->users) { + for (auto& msg : pair.second.msg_list) { + if (msg->msg_uuid() == 0) { + msg->set_msg_uuid(hum->IncDBPrivateChatLastId()); + } else if (msg->msg_uuid() > init_last_id){ + msg->set_msg_uuid(hum->IncDBPrivateChatLastId()); + } + if (msg->msg_uuid() > pair.second.last_id) { + pair.second.last_id = msg->msg_uuid(); + } + if (pair.second.curr_id > pair.second.last_id) { + pair.second.curr_id = pair.second.last_id; + } + } + } + #endif + } +} + +void ChatMgr::OnPlayerOffline(Player* hum) +{ + #if 0 + a8::Timer::Instance()->AddDeadLineTimer + (1000 * 60 * 5, + a8::XParams() + .SetSender(hum->AccountId()), + [] (const a8::XParams& param) + { + if (!PlayerMgr::Instance()->GetPlayerByAccountId(param.sender)) { + ChatMgr::Instance()->RemoveChatedUser(param.sender); + } + }); + #endif +} + +void ChatMgr::AddChatedUser(const std::string& sender_id, const std::string& receiver_id, + cs::MFChatMsg* chat_msg, long long last_id) +{ + cs::MFChatMsg* chat_msg_copy = new cs::MFChatMsg; + *chat_msg_copy = *chat_msg; + chat_msg_copy->set_msg_uuid(last_id); + ChatedUserRec* user = nullptr; + { + auto itr = private_chated_users_.find(sender_id); + if (itr == private_chated_users_.end()) { + private_chated_users_[sender_id] = new ChatedUserRec; + itr = private_chated_users_.find(sender_id); + } + user = itr->second; + } + { + user->dirty = false; + user->has_unread_msg = true; + auto itr = user->users.find(receiver_id); + if (itr == user->users.end()) { + user->users[receiver_id] = ChatMsgRec(); + itr = user->users.find(receiver_id); + } + itr->second.last_id = last_id; + itr->second.msg_list.push_back(chat_msg_copy); + itr->second.PopAndDelete(50); + } +} + +void ChatMgr::FillMFChatMsg(cs::MFChatMsg* msg, Player* sender, long long msg_uuid, + int chat_channel, int msg_type, const std::string& msg_body) +{ + #if 0 + msg->set_msg_uuid(msg_uuid); + sender->FillMFUserInfo(msg->mutable_sender()); + msg->set_chat_channel(chat_channel); + msg->set_msg_type(msg_type); + msg->set_msg_body(msg_body); + msg->set_send_time(time(nullptr)); + #endif +} + +void ChatMgr::RemoveChatedUser(const std::string& account_id) +{ + auto itr = private_chated_users_.find(account_id); + if (itr != private_chated_users_.end()) { + delete itr->second; + private_chated_users_.erase(account_id); + } +} diff --git a/server/imserver/chatmgr.h b/server/imserver/chatmgr.h new file mode 100644 index 0000000..5ad595e --- /dev/null +++ b/server/imserver/chatmgr.h @@ -0,0 +1,63 @@ +#pragma once + +#include "cs_proto.pb.h" + +struct ChatMsgRec +{ + long long curr_id = 0; + long long last_id = 0; + std::list msg_list; + + ~ChatMsgRec(); + void Pop(size_t max_num); + void PopAndDelete(size_t max_num); +}; + +class Player; +struct ChatedUserRec; +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); + void ProcTeamChat(Player* hum, const cs::CMSendChatMsg& msg); + void ProcBigHornChat(Player* hum, const cs::CMSendChatMsg& msg); + void ProcLoopMsgChat(Player* hum, const cs::CMSendChatMsg& msg); + + void SyncWorldChatMsg(Player* hum); + void SyncPrivateChatMsg(Player* hum); + void SyncGuildChatMsg(Player* hum); + + void OnPlayerOnline(Player* hum); + void OnPlayerOffline(Player* hum); + + private: + ChatedUserRec* GetChatedUser(const std::string& account_id); + void AddChatedUser(const std::string& sender_id, const std::string& receiver_id, + cs::MFChatMsg* chat_msg, long long last_id); + void FillMFChatMsg(cs::MFChatMsg* msg, Player* sender, long long msg_uuid, + int chat_channel, int msg_type, const std::string& msg_body); + void RemoveChatedUser(const std::string& account_id); + + private: + long long world_msg_id_ = 1000; + long long guild_msg_id_ = 1000; + long long temp_msg_id_ = 1000; + ChatMsgRec world_msgrec_; + std::map guild_msgrec_; + std::map private_chated_users_; + std::map team_msg_hash_; + ChatMsgRec bighorn_msgrec_; + ChatMsgRec loop_msgrec_; +}; diff --git a/server/imserver/player.h b/server/imserver/player.h index b3a321e..6be7356 100644 --- a/server/imserver/player.h +++ b/server/imserver/player.h @@ -14,7 +14,6 @@ class Player : public std::enable_shared_from_this { public: int socket_handle = 0; - std::string account_id; void _CMSendChatMsg(f8::MsgHdr& hdr, const cs::CMSendChatMsg& msg); void _CMSendCustomMsg(f8::MsgHdr& hdr, const cs::CMSendCustomMsg& msg); @@ -23,6 +22,9 @@ class Player : public std::enable_shared_from_this void _CMSetCurrPrivateChatTarget(f8::MsgHdr& hdr, const cs::CMSetCurrPrivateChatTarget& msg); std::weak_ptr GetUserInfo() { return user_info_; }; + const std::string& AccountId() { return account_id_; }; + private: + std::string account_id_; std::weak_ptr user_info_; };