#include "precompile.h" #include #include #include #include "player.h" #include "playermgr.h" #include "dbengine.h" #include "MSConnMgr.h" #include "dbengine.h" #include "app.h" #include "typeconvert.h" #include "playermgr.h" #include "IMConn.h" #include "IMConnMgr.h" #include "MSConn.h" #include "MSConnMgr.h" #include "handlermgr.h" void Player::Init() { myself.hum = this; myself.crc32_code = a8::openssl::Crc32 ( (unsigned char*)myself.base_data.account_id.data(), myself.base_data.account_id.size() ); NotifyOnline(); } void Player::UnInit() { SaveToDB(); timer_attacher.ClearTimerList(); for (auto& pair : friend_hash_) { if (!list_empty(&pair.second->watch_node)) { PlayerMgr::Instance()->UnWatchPlayer(pair.second); delete pair.second; } } friend_hash_.clear(); NotifyOffline(); } void Player::Deserialize(const ss::MFUserDB& user_db) { for (auto& friend_db : user_db.friends()) { Friend* friendobj = new Friend; TypeConvert::Convert(friend_db.base_data(), friendobj->base_data); friendobj->crc32_code = a8::openssl::Crc32 ( (unsigned char*)friendobj->base_data.account_id.data(), friendobj->base_data.account_id.size() ); friendobj->hum = this; friend_hash_[friendobj->base_data.account_id] = friendobj; PlayerMgr::Instance()->WatchPlayer(friendobj); } } void Player::Serialize(ss::MFUserDB& user_db) { for (auto& pair : friend_hash_) { auto p = user_db.add_friends(); TypeConvert::Convert(pair.second->base_data, *(p->mutable_base_data())); } } void Player::_CMPing(f8::MsgHdr& hdr, const cs::CMPing& msg) { cs::SMPing respmsg; SendMsg(respmsg); } void Player::_CMUpdateUserInfo(f8::MsgHdr& hdr, const cs::CMUpdateUserInfo& msg) { if (msg.has_nickname()) { myself.base_data.nickname = msg.nickname(); } if (msg.has_avatar_url()) { myself.base_data.avatar_url = msg.avatar_url(); } if (msg.has_sex()) { myself.base_data.sex = msg.sex(); } if (msg.has_user_value1()) { myself.base_data.user_value1 = msg.user_value1(); } if (msg.has_user_value2()) { myself.base_data.user_value2 = msg.user_value2(); } if (msg.has_user_value3()) { myself.base_data.user_value3 = msg.user_value3(); } OnDataVersion1Change(); } void Player::_CMUpdateTempCustomData(f8::MsgHdr& hdr, const cs::CMUpdateTempCustomData& msg) { if (msg.temp_custom_data().has_value1()) { myself.temp_custom_data.value1 = msg.temp_custom_data().value1(); } if (msg.temp_custom_data().has_value2()) { myself.temp_custom_data.value2 = msg.temp_custom_data().value2(); } if (msg.temp_custom_data().has_value3()) { myself.temp_custom_data.value2 = msg.temp_custom_data().value3(); } OnTempCustomDataChange(); } void Player::_CMFriendList(f8::MsgHdr& hdr, const cs::CMFriendList& msg) { PushFriendList(); } void Player::_CMFriendApply(f8::MsgHdr& hdr, const cs::CMFriendApply& msg) { cs::SMFriendApply respmsg; if (GetFriendById(msg.friend_id())) { respmsg.set_errcode(1); respmsg.set_errmsg("已经是好友"); SendMsg(respmsg); return; } if (msg.friend_id() == AccountId()) { respmsg.set_errcode(21); respmsg.set_errmsg("不能邀请自己"); SendMsg(respmsg); return; } SendMsg(respmsg); { auto on_ok = [] (a8::XParams& param, const f8::DataSet* data_set) { }; auto on_error = [] (a8::XParams& param, int error_code, const std::string& error_msg) { }; long long friend_crc32_code = a8::openssl::Crc32( (unsigned char*)msg.friend_id().data(), msg.friend_id().size() ); a8::XObject conn_info = DBEngine::Instance()->GetConnInfo(friend_crc32_code); DBEngine::Instance()->ExecAsyncScript ( conn_info, "INSERT INTO `friend_apply`(applyid, target_id, sender_id, sender_nickname, " " sender_avatar_url, sender_sex, sender_data_version1, " " createtime, sender_user_value1, sender_user_value2, sender_user_value3, status)" "VALUES(%d, '%s', '%s', '%s', '%s', %d, %d, %d, %d, %d, %d, 0);", { App::Instance()->NewUUID(), msg.friend_id(), myself.base_data.account_id, myself.base_data.nickname, myself.base_data.avatar_url, myself.base_data.sex, myself.base_data.base_data_version, myself.base_data.user_value1, myself.base_data.user_value2, myself.base_data.user_value3, App::Instance()->nowtime }, a8::XParams(), on_ok, on_error, friend_crc32_code ); } } void Player::_CMFriendApplyList(f8::MsgHdr& hdr, const cs::CMFriendApplyList& msg) { #if 0 if (last_apply_idx_ > 0 && last_apply_idx_ >= DBEngine::Instance()->GetFriendApplyCurrIdx(myself.crc32_code)) { cs::SMFriendApplyList respmsg; FillApplyList(msg.paging(), respmsg); SendMsg(respmsg); return; } #endif auto on_ok = [] (a8::XParams& param, const f8::DataSet* data_set) { cs::MFPaging* paging = (cs::MFPaging*)param.param2.GetUserData(); Player* hum = PlayerMgr::Instance()->GetPlayerByAccountId(param.sender.GetString()); if (hum && hum->socket_handle == param.param1.GetInt()) { for (auto& row : *data_set) { FriendApply apply; apply.idx = a8::XValue(row[0]); apply.applyid = a8::XValue(row[1]); apply.target_id = row[2]; apply.base_data.account_id = row[3]; apply.base_data.nickname = row[4]; apply.base_data.avatar_url = row[5]; apply.base_data.sex = a8::XValue(row[6]); apply.base_data.base_data_version = a8::XValue(row[7]); apply.base_data.user_value1 = a8::XValue(row[8]); apply.base_data.user_value2 = a8::XValue(row[9]); apply.base_data.user_value3 = a8::XValue(row[10]); hum->apply_list_.push_back(apply); #if 0 if (apply.idx > hum->last_apply_idx_) { hum->last_apply_idx_ = apply.idx; } #endif } cs::SMFriendApplyList respmsg; hum->FillApplyList(*paging, respmsg); hum->SendMsg(respmsg); hum->apply_list_.clear(); } delete paging; }; auto on_error = [] (a8::XParams& param, int error_code, const std::string& error_msg) { cs::MFPaging* paging = (cs::MFPaging*)param.param2.GetUserData(); Player* hum = PlayerMgr::Instance()->GetPlayerByAccountId(param.sender.GetString()); if (hum && hum->socket_handle == param.param1.GetInt()) { cs::SMFriendApplyList respmsg; hum->FillApplyList(*paging, respmsg); hum->SendMsg(respmsg); } delete paging; }; cs::MFPaging* paging_copy = new cs::MFPaging; *paging_copy = msg.paging(); #if 1 paging_copy->set_curr_page(0); paging_copy->set_page_size(100); #endif a8::XObject conn_info = DBEngine::Instance()->GetConnInfo(myself.crc32_code); DBEngine::Instance()->ExecAsyncQuery ( conn_info, "SELECT idx, applyid, target_id, sender_id, sender_nickname, " " sender_avatar_url, sender_sex, sender_data_version1, " " sender_user_value1, sender_user_value2, sender_user_value3, status " "FROM friend_apply WHERE idx > %d AND target_id='%s' AND status=0;", { last_apply_idx_, myself.base_data.account_id }, a8::XParams() .SetSender(myself.base_data.account_id) .SetParam1(hdr.socket_handle) .SetParam2(paging_copy), on_ok, on_error, myself.crc32_code ); } void Player::_CMFriendAgree(f8::MsgHdr& hdr, const cs::CMFriendAgree& msg) { cs::SMFriendAgree respmsg; if (GetFriendById(msg.apply().base_data().account_id())) { respmsg.set_errcode(0); respmsg.set_errmsg(""); SendMsg(respmsg); return; } if (msg.apply().base_data().account_id() == AccountId()) { respmsg.set_errcode(2); respmsg.set_errmsg("不能添加自己"); SendMsg(respmsg); return; } Friend* friendobj = new Friend; TypeConvert::Convert(msg.apply().base_data(), friendobj->base_data); friendobj->crc32_code = a8::openssl::Crc32 ( (unsigned char*)friendobj->base_data.account_id.data(), friendobj->base_data.account_id.size() ); friendobj->hum = this; friend_hash_[friendobj->base_data.account_id] = friendobj; NotifyUserInfoUpdate(friendobj); PlayerMgr::Instance()->WatchPlayer(friendobj); SendMsg(respmsg); MarkDirty(); #if 1 { Player* hum = PlayerMgr::Instance()->GetPlayerByAccountId(friendobj->base_data.account_id); if (hum) { hum->AddFriend(&myself); } } #endif a8::XObject conn_info = DBEngine::Instance()->GetConnInfo(myself.crc32_code); DBEngine::Instance()->ExecAsyncScript ( conn_info, "UPDATE `friend_apply` SET status=1 WHERE target_id='%s' AND sender_id='%s';", { msg.apply().target_id(), msg.apply().base_data().account_id(), }, a8::XParams(), nullptr, nullptr, myself.crc32_code ); } void Player::_CMFriendRefuse(f8::MsgHdr& hdr, const cs::CMFriendRefuse& msg) { cs::SMFriendRefuse respmsg; SendMsg(respmsg); a8::XObject conn_info = DBEngine::Instance()->GetConnInfo(myself.crc32_code); DBEngine::Instance()->ExecAsyncScript ( conn_info, "UPDATE `friend_apply` SET status=2 WHERE idx=%d AND target_id='%s' AND sender_id='%s';", { msg.apply().idx(), msg.apply().target_id(), msg.apply().base_data().account_id(), }, a8::XParams(), nullptr, nullptr, myself.crc32_code ); } void Player::_CMFriendIgnore(f8::MsgHdr& hdr, const cs::CMFriendIgnore& msg) { cs::SMFriendIgnore respmsg; SendMsg(respmsg); a8::XObject conn_info = DBEngine::Instance()->GetConnInfo(myself.crc32_code); DBEngine::Instance()->ExecAsyncScript ( conn_info, "UPDATE `friend_apply` SET status=3 WHERE idx=%d AND target_id='%s' AND sender_id='%s';", { msg.apply().idx(), msg.apply().target_id(), msg.apply().base_data().account_id(), }, a8::XParams(), nullptr, nullptr, myself.crc32_code ); } void Player::_CMFriendDelete(f8::MsgHdr& hdr, const cs::CMFriendDelete& msg) { cs::SMFriendDelete respmsg; Friend* p = GetFriendById(msg.friend_id()); if (p) { friend_hash_.erase(msg.friend_id()); MarkDirty(); #if 1 { Player* hum = PlayerMgr::Instance()->GetPlayerByAccountId(p->base_data.account_id); if (hum) { hum->RemoveFriend(AccountId()); } } #endif } respmsg.set_friend_id(msg.friend_id()); SendMsg(respmsg); { cs::SMDeleteFriendNotify notifymsg; notifymsg.add_user_list(msg.friend_id()); SendMsg(notifymsg); } } void Player::_CMFriendBlackList(f8::MsgHdr& hdr, const cs::CMFriendBlackList& msg) { } void Player::_CMFriendAddBlack(f8::MsgHdr& hdr, const cs::CMFriendAddBlack& msg) { } void Player::_CMFriendDeleteBlack(f8::MsgHdr& hdr, const cs::CMFriendDeleteBlack& msg) { } void Player::_CMSendChatMsg(f8::MsgHdr& hdr, const cs::CMSendChatMsg& msg) { ss::SS_IM_SendChatMsg ss_msg; FillIMMsgConext(hdr, ss_msg.mutable_context()); ss_msg.set_chat_channel(msg.chat_channel()); ss_msg.set_msg(msg.msg()); Friend* friend_data = GetFriendById(msg.target()); if (friend_data) { SendSSMsg(*friend_data, ss_msg); } } void Player::_CMSendCustomMsg(f8::MsgHdr& hdr, const cs::CMSendCustomMsg& msg) { ss::SS_IM_SendCustomMsg ss_msg; FillIMMsgConext(hdr, ss_msg.mutable_context()); ss_msg.set_msg(msg.msg()); ss_msg.set_param1(msg.param1()); ss_msg.set_param2(msg.param2()); ss_msg.set_param3(msg.param3()); for (auto& target_id : msg.target_list()) { Friend* friend_data = GetFriendById(target_id); if (friend_data) { SendSSMsg(*friend_data, ss_msg); } } } void Player::_CMGroupCreate(f8::MsgHdr& hdr, const cs::CMGroupCreate& msg) { #if 0 if (myself.base_data.group_id != 0) { cs::SMGroupCreate respmsg; respmsg.set_errcode(1); respmsg.set_errmsg("你已经有群"); SendMsg(respmsg); return; } ForwardGroupCMMsg(hdr, App::Instance()->NewUUID()); #endif } void Player::_CMGroupJoin(f8::MsgHdr& hdr, const cs::CMGroupJoin& msg) { #if 0 if (myself.base_data.group_id != 0) { cs::SMGroupJoin respmsg; respmsg.set_errcode(1); respmsg.set_errmsg("你已经有群"); SendMsg(respmsg); return; } ForwardGroupCMMsg(hdr, myself.base_data.group_id); #endif } void Player::_CMGroupAgree(f8::MsgHdr& hdr, const cs::CMGroupAgree& msg) { #if 0 if (myself.base_data.group_id == 0) { cs::SMGroupAgree respmsg; respmsg.set_errcode(2); respmsg.set_errmsg("你还没有群"); SendMsg(respmsg); return; } ForwardGroupCMMsg(hdr, myself.base_data.group_id); #endif } void Player::_CMGroupKick(f8::MsgHdr& hdr, const cs::CMGroupKick& msg) { #if 0 if (myself.base_data.group_id == 0) { cs::SMGroupKick respmsg; respmsg.set_errcode(2); respmsg.set_errmsg("你还没有群"); SendMsg(respmsg); return; } ForwardGroupCMMsg(hdr, myself.base_data.group_id); #endif } void Player::_CMGroupQuit(f8::MsgHdr& hdr, const cs::CMGroupQuit& msg) { #if 0 if (myself.base_data.group_id == 0) { cs::SMGroupQuit respmsg; respmsg.set_errcode(2); respmsg.set_errmsg("你还没有群"); SendMsg(respmsg); return; } ForwardGroupCMMsg(hdr, myself.base_data.group_id); #endif } void Player::_CMGroupDismiss(f8::MsgHdr& hdr, const cs::CMGroupDismiss& msg) { #if 0 if (myself.base_data.group_id == 0) { cs::SMGroupQuit respmsg; respmsg.set_errcode(2); respmsg.set_errmsg("你还没有群"); SendMsg(respmsg); return; } ForwardGroupCMMsg(hdr, myself.base_data.group_id); #endif } void Player::_CMGroupRename(f8::MsgHdr& hdr, const cs::CMGroupRename& msg) { #if 0 if (myself.base_data.group_id == 0) { cs::SMGroupRename respmsg; respmsg.set_errcode(2); respmsg.set_errmsg("你还没有群"); SendMsg(respmsg); return; } ForwardGroupCMMsg(hdr, myself.base_data.group_id); #endif } void Player::ReLogin(f8::MsgHdr& hdr, const cs::CMLogin& msg) { cs::SMLogin respmsg; WSListener::Instance()->SendToClient(hdr.socket_handle, 0, respmsg); PlayerMgr::Instance()->ReBindSocket(hdr.socket_handle, this); } void Player::FillFriendList(::google::protobuf::RepeatedPtrField< ::cs::MFUserInfo >* friend_list) { { auto p = friend_list->Add(); TypeConvert::Convert(myself.base_data, *(p->mutable_base_data())); TypeConvert::Convert(myself.temp_custom_data, *(p->mutable_temp_custom_data())); } for (auto& pair : friend_hash_) { auto p = friend_list->Add(); TypeConvert::Convert(pair.second->base_data, *(p->mutable_base_data())); TypeConvert::Convert(pair.second->temp_custom_data, *(p->mutable_temp_custom_data())); } } void Player::FillIMMsgConext(f8::MsgHdr& hdr, ss::MFIMMsgConext* conext) { #if 0 conext->set_socket_handle(hdr.socket_handle); conext->set_account_id(myself.base_data.account_id); conext->set_nickname(myself.base_data.nickname); conext->set_avatar_url(myself.base_data.avatar_url); conext->set_sex(myself.base_data.sex); #if 1 conext->set_online(true); #else conext->set_online(online); #endif conext->set_msgid(hdr.msgid); #endif } void Player::ForwardGroupCMMsg(f8::MsgHdr& hdr, long long hash_code) { ss::SS_MS_ForwardGroupCMMsg msg; FillIMMsgConext(hdr, msg.mutable_context()); if (hdr.buflen > 0) { msg.mutable_payload()->assign(hdr.buf, hdr.buflen); } MSConnMgr::Instance()->SendMsg(msg, hash_code); } void Player::FillMFUserInfo(cs::MFUserInfo* user_info) { } void Player::MarkDirty() { if (!dirty_) { dirty_ = true; dirty_timer_ = a8::Timer::Instance()-> AddDeadLineTimerAndAttach(1000 * 60, a8::XParams() .SetSender((void*)this), [] (const a8::XParams& param) { Player* hum = (Player*)param.sender.GetUserData(); hum->SaveToDB(); }, &timer_attacher.timer_list_, [] (const a8::XParams& param) { Player* hum = (Player*)param.sender.GetUserData(); hum->dirty_timer_ = nullptr; } ); } } void Player::SaveToDB() { ss::MFUserDB user_db; Serialize(user_db); std::string friend_data; user_db.SerializeToString(&friend_data); auto on_ok = [] (a8::XParams& param, const f8::DataSet* data_set) { }; auto on_error = [] (a8::XParams& param, int error_code, const std::string& error_msg) { printf("xxxxx=n"); }; a8::XObject conn_info = DBEngine::Instance()->GetConnInfo(myself.crc32_code); DBEngine::Instance()-> ExecAsyncScript( conn_info, "UPDATE `user` SET friend_data='%s', modifytime=%d, " " nickname='%s', avatar_url='%s', sex=%d, data_version1=%d " "WHERE account_id='%s';", { friend_data, App::Instance()->nowtime, myself.base_data.nickname, myself.base_data.avatar_url, myself.base_data.sex, myself.base_data.base_data_version, myself.base_data.account_id }, a8::XParams(), on_ok, on_error, myself.crc32_code ); } Friend* Player::GetFriendById(const std::string& friend_id) { auto itr = friend_hash_.find(friend_id); return itr != friend_hash_.end() ? itr->second : nullptr; } void Player::FillApplyList(const cs::MFPaging& paging, cs::SMFriendApplyList& respmsg) { int i = 0; int start = paging.curr_page() * paging.page_size(); for (const FriendApply& apply : apply_list_) { if (i >= start && i < start + paging.page_size()) { TypeConvert::Convert(apply, *respmsg.add_apply_list()); } ++i; } *respmsg.mutable_paging() = paging; if (paging.page_size() > 0) { respmsg.mutable_paging()->set_total_page(ceil(i / paging.page_size())); } else { respmsg.mutable_paging()->set_total_page(1); } } void Player::NotifyOnline() { } void Player::NotifyOffline() { } void Player::OnDataVersion1Change() { ++myself.base_data.base_data_version; if (!update_user_info_timer_) { update_user_info_timer_ = a8::Timer::Instance()->AddDeadLineTimerAndAttach ( 1000 * 3, a8::XParams() .SetSender(this), [] (const a8::XParams& param) { Player* hum = (Player*)param.sender.GetUserData(); hum->InternalUpdateUserInfo(); }, &timer_attacher.timer_list_, [] (const a8::XParams& param) { Player* hum = (Player*)param.sender.GetUserData(); hum->update_user_info_timer_ = nullptr; } ); } } void Player::OnTempCustomDataChange() { if (!update_user_info_timer_) { update_user_info_timer_ = a8::Timer::Instance()->AddDeadLineTimerAndAttach ( 1000 * 3, a8::XParams() .SetSender(this), [] (const a8::XParams& param) { Player* hum = (Player*)param.sender.GetUserData(); hum->InternalUpdateUserInfo(); }, &timer_attacher.timer_list_, [] (const a8::XParams& param) { Player* hum = (Player*)param.sender.GetUserData(); hum->update_user_info_timer_ = nullptr; } ); } } void Player::InternalSendSSMsg(const Friend& friend_data, int msgid, ::google::protobuf::Message& msg) { if (friend_data.server_key.empty()) { return; } IMConn* conn = IMConnMgr::Instance()->GetConnByKey(friend_data.server_key); if (conn) { conn->SendMsg(msgid, msg); } #if 1 { Player* hum = PlayerMgr::Instance()->GetPlayerByAccountId(friend_data.base_data.account_id); if (hum) { f8::NetMsgHandler* handler = f8::GetNetMsgHandler(&HandlerMgr::Instance()->imcmsghandler, msgid); if (!handler || handler->handlerid != HID_PlayerMgr) { return; } f8::MsgHdr hdr; hdr.msgid = msgid; hdr.seqid = 0; hdr.socket_handle = 0; int packlen = msg.ByteSize(); char* buff = nullptr; if (packlen) { buff = (char*)malloc(packlen); msg.SerializeToArray(buff, packlen); } hdr.buf = buff; hdr.buflen = packlen; hdr.offset = 0; hdr.ip_saddr = 0; ProcessNetMsg(handler, PlayerMgr::Instance(), hdr); if (buff) { free(buff); } } } #endif } void Player::AddFriend(Friend* p) { if (!GetFriendById(p->base_data.account_id)) { Friend* friendobj = new Friend; *friendobj = *p; INIT_LIST_HEAD(&friendobj->watch_node); friendobj->crc32_code = a8::openssl::Crc32 ( (unsigned char*)friendobj->base_data.account_id.data(), friendobj->base_data.account_id.size() ); friendobj->hum = this; friend_hash_[friendobj->base_data.account_id] = friendobj; NotifyUserInfoUpdate(friendobj); PlayerMgr::Instance()->WatchPlayer(friendobj); } } void Player::RemoveFriend(const std::string& account_id) { Friend* friendobj = GetFriendById(account_id); if (friendobj) { { cs::SMDeleteFriendNotify notifymsg; notifymsg.add_user_list(account_id); SendMsg(notifymsg); } PlayerMgr::Instance()->UnWatchPlayer(friendobj); friend_hash_.erase(account_id); delete friendobj; } } const std::string Player::AccountId() { return myself.base_data.account_id; } void Player::InternalUpdateUserInfo() { ss::SS_IM_UpdateUserInfo ss_msg; FillMFUserInfo(ss_msg.mutable_user_info()); MSConnMgr::Instance()->TraverseMSConn ( [&ss_msg] (MSConn* conn) { conn->SendMsg(ss_msg); return true; } ); IMConnMgr::Instance()->TraverseIMConn ( [&ss_msg] (IMConn* conn) { conn->SendMsg(ss_msg); return true; } ); NotifyUserInfoUpdate(&myself); MarkDirty(); } void Player::NotifyUserInfoUpdate(Friend* friend_data) { cs::SMUserInfoUpdate msg; auto p = msg.add_user_infos(); TypeConvert::Convert(friend_data->base_data, *p->mutable_base_data()); TypeConvert::Convert(friend_data->temp_custom_data, *p->mutable_temp_custom_data()); SendMsg(msg); } void Player::PushFriendList() { cs::SMFriendList respmsg; FillFriendList(respmsg.mutable_friend_list()); SendMsg(respmsg); }