aozhiwei 092d5a654a 1
2020-06-17 19:57:02 +08:00

695 lines
20 KiB
C++

#include "precompile.h"
#include <math.h>
#include <a8/openssl.h>
#include <a8/timer.h>
#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"
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()
);
SyncLocToMasterServer();
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();
}
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();
}
++myself.base_data.base_data_version;
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_group_id, sender_data_version1, "
" createtime)"
"VALUES(%d, '%s', '%s', '%s', '%s', %d, %d, %d, %d);",
{
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.group_id,
myself.base_data.base_data_version,
App::Instance()->nowtime
},
a8::XParams(),
on_ok,
on_error,
friend_crc32_code
);
}
}
void Player::_CMFriendApplyList(f8::MsgHdr& hdr, const cs::CMFriendApplyList& msg)
{
if (last_apply_idx_ > 0 &&
last_apply_idx_ >= DBEngine::Instance()->GetFriendApplyCurrIdx(myself.crc32_code)) {
cs::SMFriendApplyList respmsg;
FillApplyList(msg.paging(), respmsg);
SendMsg(respmsg);
return;
}
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]);
hum->apply_list_.push_back(apply);
if (apply.idx > hum->last_apply_idx_) {
hum->last_apply_idx_ = apply.idx;
}
}
cs::SMFriendApplyList respmsg;
hum->FillApplyList(*paging, respmsg);
hum->SendMsg(respmsg);
}
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_group_id, sender_data_version1 "
"FROM friend_apply WHERE idx > %d AND target_id='%s';",
{
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;
PlayerMgr::Instance()->WatchPlayer(friendobj);
SendMsg(respmsg);
}
void Player::_CMFriendRefuse(f8::MsgHdr& hdr, const cs::CMFriendRefuse& msg)
{
cs::SMFriendRefuse respmsg;
SendMsg(respmsg);
}
void Player::_CMFriendIgnore(f8::MsgHdr& hdr, const cs::CMFriendIgnore& msg)
{
cs::SMFriendIgnore respmsg;
SendMsg(respmsg);
}
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());
}
respmsg.set_friend_id(msg.friend_id());
SendMsg(respmsg);
}
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 (myself.base_data.group_id != 0) {
cs::SMGroupCreate respmsg;
respmsg.set_errcode(1);
respmsg.set_errmsg("你已经有群");
SendMsg(respmsg);
return;
}
ForwardGroupCMMsg(hdr, App::Instance()->NewUUID());
}
void Player::_CMGroupJoin(f8::MsgHdr& hdr, const cs::CMGroupJoin& msg)
{
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);
}
void Player::_CMGroupAgree(f8::MsgHdr& hdr, const cs::CMGroupAgree& msg)
{
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);
}
void Player::_CMGroupKick(f8::MsgHdr& hdr, const cs::CMGroupKick& msg)
{
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);
}
void Player::_CMGroupQuit(f8::MsgHdr& hdr, const cs::CMGroupQuit& msg)
{
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);
}
void Player::_CMGroupDismiss(f8::MsgHdr& hdr, const cs::CMGroupDismiss& msg)
{
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);
}
void Player::_CMGroupRename(f8::MsgHdr& hdr, const cs::CMGroupRename& msg)
{
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);
}
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);
SyncLocToMasterServer();
}
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)
{
};
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, group_id=%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.group_id,
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::SyncLocToMasterServer()
{
}
void Player::NotifyOnline()
{
}
void Player::NotifyOffline()
{
}
void Player::OnDataVersion1Change()
{
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);
}
}
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);
}