This commit is contained in:
azw 2023-02-19 06:43:00 +00:00
parent c69747652e
commit 8f2a129f4b
3 changed files with 485 additions and 1 deletions

419
server/imserver/chatmgr.cc Normal file
View File

@ -0,0 +1,419 @@
#include "precompile.h"
#include <f8/timer.h>
#include "chatmgr.h"
#include "player.h"
#include "playermgr.h"
struct ChatedUserRec
{
bool has_unread_msg = false;
bool dirty = false;
std::map<std::string, ChatMsgRec> 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
([&notifymsg](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
([&notifymsg](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);
}
}

63
server/imserver/chatmgr.h Normal file
View File

@ -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<cs::MFChatMsg*> msg_list;
~ChatMsgRec();
void Pop(size_t max_num);
void PopAndDelete(size_t max_num);
};
class Player;
struct ChatedUserRec;
class ChatMgr : public a8::Singleton<ChatMgr>
{
private:
ChatMgr() {};
friend class a8::Singleton<ChatMgr>;
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<long long, ChatMsgRec> guild_msgrec_;
std::map<std::string, ChatedUserRec*> private_chated_users_;
std::map<std::string, cs::MFChatMsg*> team_msg_hash_;
ChatMsgRec bighorn_msgrec_;
ChatMsgRec loop_msgrec_;
};

View File

@ -14,7 +14,6 @@ class Player : public std::enable_shared_from_this<Player>
{
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<Player>
void _CMSetCurrPrivateChatTarget(f8::MsgHdr& hdr, const cs::CMSetCurrPrivateChatTarget& msg);
std::weak_ptr<UserInfo> GetUserInfo() { return user_info_; };
const std::string& AccountId() { return account_id_; };
private:
std::string account_id_;
std::weak_ptr<UserInfo> user_info_;
};