441 lines
14 KiB
C++
441 lines
14 KiB
C++
#include "precompile.h"
|
|
|
|
#include <a8/openssl.h>
|
|
#include <a8/udplog.h>
|
|
|
|
#include "playermgr.h"
|
|
#include "player.h"
|
|
#include "cs_proto.pb.h"
|
|
#include "dbengine.h"
|
|
#include "WSListener.h"
|
|
#include "app.h"
|
|
|
|
#include "framework/cpp/utils.h"
|
|
|
|
void PlayerMgr::Init()
|
|
{
|
|
}
|
|
|
|
void PlayerMgr::UnInit()
|
|
{
|
|
}
|
|
|
|
void PlayerMgr::_SS_WSP_SocketDisconnect(f8::MsgHdr& hdr, const ss::SS_WSP_SocketDisconnect& msg)
|
|
{
|
|
OnClientSocketDisconnect(hdr.socket_handle);
|
|
}
|
|
|
|
void PlayerMgr::_SS_MS_PushUserList(f8::MsgHdr& hdr, const ss::SS_MS_PushUserList& msg)
|
|
{
|
|
|
|
}
|
|
|
|
void PlayerMgr::_SS_IM_SendChatMsg(f8::MsgHdr& hdr, const ss::SS_IM_SendChatMsg& msg)
|
|
{
|
|
Player* hum = GetPlayerByAccountId(msg.target());
|
|
if (hum) {
|
|
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);
|
|
}
|
|
}
|
|
|
|
void PlayerMgr::_SS_IM_SendCustomMsg(f8::MsgHdr& hdr, const ss::SS_IM_SendCustomMsg& msg)
|
|
{
|
|
Player* hum = GetPlayerByAccountId(msg.target());
|
|
if (hum) {
|
|
cs::SMCustomMsgNotify notifymsg;
|
|
notifymsg.set_sender(msg.context().user_info().base_data().account_id());
|
|
notifymsg.set_msg(msg.msg());
|
|
notifymsg.set_param1(msg.param1());
|
|
notifymsg.set_param2(msg.param2());
|
|
notifymsg.set_param3(msg.param3());
|
|
hum->SendMsg(notifymsg);
|
|
}
|
|
}
|
|
|
|
void PlayerMgr::_SS_IM_FriendAgreeRequest(f8::MsgHdr& hdr, const ss::SS_IM_FriendAgreeRequest& msg)
|
|
{
|
|
Player* hum = GetPlayerByAccountId(msg.target_id());
|
|
if (hum) {
|
|
hum->_SS_IM_FriendAgreeRequest(hdr, msg);
|
|
}
|
|
}
|
|
|
|
void PlayerMgr::_SS_IM_FriendDeleteRequest(f8::MsgHdr& hdr, const ss::SS_IM_FriendDeleteRequest& msg)
|
|
{
|
|
Player* hum = GetPlayerByAccountId(msg.target_id());
|
|
if (hum) {
|
|
hum->_SS_IM_FriendDeleteRequest(hdr, msg);
|
|
}
|
|
}
|
|
|
|
void PlayerMgr::_SS_IM_UpdateUserInfo(f8::MsgHdr& hdr, const ss::SS_IM_UpdateUserInfo& msg)
|
|
{
|
|
auto itr = watch_players_.find(msg.user_info().base_data().account_id());
|
|
if (itr != watch_players_.end()) {
|
|
struct Friend *node, *tmp;
|
|
list_for_each_entry_safe(node, tmp, &itr->second, watch_node) {
|
|
node->hum->NotifyUserInfoUpdate(node);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PlayerMgr::_CMLogin(f8::MsgHdr& hdr, const cs::CMLogin& msg)
|
|
{
|
|
Player* hum = GetPlayerByAccountId(msg.account_id());
|
|
if (hum) {
|
|
hum->ReLogin(hdr, msg);
|
|
return;
|
|
}
|
|
if (GetHdrBySocket(hdr.socket_handle) ||
|
|
GetHdrByAccountId(msg.account_id())) {
|
|
cs::SMLogin respmsg;
|
|
respmsg.set_errcode(1);
|
|
respmsg.set_errmsg("登录失败请重试");
|
|
WSListener::Instance()->SendToClient(hdr.socket_handle, 0, respmsg);
|
|
return;
|
|
}
|
|
f8::MsgHdr* new_hdr = hdr.Clone();
|
|
pending_socket_hash_[hdr.socket_handle] = std::make_tuple(msg.account_id(), new_hdr);
|
|
pending_account_hash_[msg.account_id()] = new_hdr;
|
|
AsyncLogin1(msg);
|
|
}
|
|
|
|
void PlayerMgr::WatchPlayer(Friend* friend_data)
|
|
{
|
|
#ifdef DEBUG
|
|
if (!list_empty(&friend_data->watch_node)) {
|
|
abort();
|
|
}
|
|
#endif
|
|
auto itr = watch_players_.find(friend_data->base_data.account_id);
|
|
if (itr == watch_players_.end()) {
|
|
watch_players_[friend_data->base_data.account_id] = list_head();
|
|
itr = watch_players_.find(friend_data->base_data.account_id);
|
|
if (itr == watch_players_.end()) {
|
|
abort();
|
|
}
|
|
INIT_LIST_HEAD(&itr->second);
|
|
}
|
|
list_add(&friend_data->watch_node, &itr->second);
|
|
}
|
|
|
|
void PlayerMgr::UnWatchPlayer(Friend* friend_data)
|
|
{
|
|
if (!list_empty(&friend_data->watch_node)) {
|
|
list_del_init(&friend_data->watch_node);
|
|
}
|
|
{
|
|
auto itr = watch_players_.find(friend_data->base_data.account_id);
|
|
if (itr != watch_players_.end()) {
|
|
if (list_empty(&itr->second)) {
|
|
watch_players_.erase(itr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int PlayerMgr::OnlineNum()
|
|
{
|
|
return socket_hash_.size();
|
|
}
|
|
|
|
void PlayerMgr::Update(long long tick)
|
|
{
|
|
for (auto& pair : accountid_hash_) {
|
|
pair.second->Update(tick);
|
|
}
|
|
}
|
|
|
|
Player* PlayerMgr::GetPlayerBySocket(int socket)
|
|
{
|
|
auto itr = socket_hash_.find(socket);
|
|
return itr != socket_hash_.end() ? itr->second : nullptr;
|
|
}
|
|
|
|
Player* PlayerMgr::GetPlayerByAccountId(const std::string& account_id)
|
|
{
|
|
auto itr = accountid_hash_.find(account_id);
|
|
return itr != accountid_hash_.end() ? itr->second : nullptr;
|
|
}
|
|
|
|
void PlayerMgr::ReBindSocket(int socket_handle, Player* hum)
|
|
{
|
|
socket_hash_.erase(hum->socket_handle);
|
|
socket_hash_[socket_handle] = hum;
|
|
hum->socket_handle = socket_handle;
|
|
}
|
|
|
|
void PlayerMgr::OnWSProxyDisconnect(a8::XParams& param)
|
|
{
|
|
int ws_socket = param.sender;
|
|
|
|
std::vector<int> socket_list;
|
|
for (auto& pair : socket_hash_) {
|
|
unsigned short parent_socket_handle = (pair.first >> 16) & 0xFFFF;
|
|
if (parent_socket_handle == ws_socket) {
|
|
socket_list.push_back(pair.first);
|
|
}
|
|
}
|
|
for (int socket_handle : socket_list) {
|
|
OnClientSocketDisconnect(socket_handle);
|
|
}
|
|
a8::UdpLog::Instance()->Warning
|
|
(
|
|
"OnWSProxyDisconnect %d",
|
|
{
|
|
ws_socket
|
|
});
|
|
}
|
|
|
|
void PlayerMgr::OnClientDisconnect(a8::XParams& param)
|
|
{
|
|
int gg_socket = param.sender;
|
|
|
|
std::vector<int> socket_list;
|
|
for (auto& pair : socket_hash_) {
|
|
unsigned short parent_socket_handle = (pair.first >> 16) & 0xFFFF;
|
|
if (parent_socket_handle == gg_socket) {
|
|
socket_list.push_back(pair.first);
|
|
}
|
|
}
|
|
for (int socket_handle : socket_list) {
|
|
Player* hum = GetPlayerBySocket(socket_handle);
|
|
if (hum) {
|
|
RemovePlayerBySocket(socket_handle);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PlayerMgr::RemovePlayerBySocket(int socket_handle)
|
|
{
|
|
auto itr = socket_hash_.find(socket_handle);
|
|
if (itr != socket_hash_.end()) {
|
|
itr->second->socket_handle = 0;
|
|
socket_hash_.erase(itr);
|
|
}
|
|
}
|
|
|
|
f8::MsgHdr* PlayerMgr::GetHdrBySocket(int socket_handle)
|
|
{
|
|
auto itr = pending_socket_hash_.find(socket_handle);
|
|
return itr != pending_socket_hash_.end() ? std::get<1>(itr->second) : nullptr;
|
|
}
|
|
|
|
f8::MsgHdr* PlayerMgr::GetHdrByAccountId(const std::string& account_id)
|
|
{
|
|
auto itr = pending_account_hash_.find(account_id);
|
|
return itr != pending_account_hash_.end() ? itr->second : nullptr;
|
|
}
|
|
|
|
void PlayerMgr::AsyncLogin1(const cs::CMLogin& msg)
|
|
{
|
|
auto on_ok =
|
|
[] (a8::XParams& param, const f8::DataSet* data_set)
|
|
{
|
|
cs::CMLogin* msg = (cs::CMLogin*)param.sender.GetUserData();
|
|
PlayerMgr::Instance()->AsyncLogin2(*msg);
|
|
delete msg;
|
|
};
|
|
auto on_error =
|
|
[] (a8::XParams& param, int error_code, const std::string& error_msg)
|
|
{
|
|
cs::CMLogin* msg = (cs::CMLogin*)param.sender.GetUserData();
|
|
PlayerMgr::Instance()->AsyncLoginOnError(
|
|
msg->account_id(),
|
|
1,
|
|
1,
|
|
""
|
|
);
|
|
delete msg;
|
|
};
|
|
cs::CMLogin* msg_copy = new cs::CMLogin();
|
|
*msg_copy = msg;
|
|
a8::XObject conn_info = DBEngine::Instance()->GetConnInfo(msg.account_id());
|
|
DBEngine::Instance()->ExecAsyncScript
|
|
(conn_info,
|
|
"INSERT INTO `user`(account_id, nickname, avatar_url,"
|
|
" sex, friend_data, createtime, modifytime, registertime)"
|
|
"VALUES ('%s', '%s', '%s', %d, '', %d, %d, %d)"
|
|
"ON DUPLICATE KEY UPDATE nickname='%s', avatar_url='%s',"
|
|
" sex=%d, last_logintime=%d, data_version1=data_version1 + 1;",
|
|
{
|
|
msg.account_id(),
|
|
msg.nickname(),
|
|
msg.avatar_url(),
|
|
msg.sex(),
|
|
App::Instance()->nowtime,
|
|
App::Instance()->nowtime,
|
|
f8::ExtractRegisterTimeFromSessionId(msg.session_id()),
|
|
msg.nickname(),
|
|
msg.avatar_url(),
|
|
msg.sex(),
|
|
App::Instance()->nowtime
|
|
},
|
|
a8::XParams()
|
|
.SetSender((void*)msg_copy),
|
|
on_ok,
|
|
on_error,
|
|
a8::openssl::Crc32((unsigned char*)msg.account_id().data(),
|
|
msg.account_id().size())
|
|
);
|
|
}
|
|
|
|
void PlayerMgr::AsyncLogin2(const cs::CMLogin& msg)
|
|
{
|
|
auto on_ok =
|
|
[] (a8::XParams& param, const f8::DataSet* data_set)
|
|
{
|
|
cs::CMLogin* msg = (cs::CMLogin*)param.sender.GetUserData();
|
|
if (data_set->empty()) {
|
|
PlayerMgr::Instance()->AsyncLoginOnError(
|
|
msg->account_id(),
|
|
2,
|
|
1,
|
|
""
|
|
);
|
|
} else {
|
|
PlayerMgr::Instance()->AsyncLoginOnOk
|
|
(
|
|
data_set->at(0).at(0), //account_id
|
|
data_set->at(0).at(1), //nickname
|
|
data_set->at(0).at(2), //avatar_url
|
|
a8::XValue(data_set->at(0).at(3)), //sex
|
|
a8::XValue(data_set->at(0).at(4)), //data_version1
|
|
data_set->at(0).at(5), //friend_data
|
|
a8::XValue(data_set->at(0).at(6)), //user_value1
|
|
a8::XValue(data_set->at(0).at(7)), //user_value2
|
|
a8::XValue(data_set->at(0).at(8)) //user_value3
|
|
);
|
|
}
|
|
delete msg;
|
|
};
|
|
auto on_error =
|
|
[] (a8::XParams& param, int error_code, const std::string& error_msg)
|
|
{
|
|
cs::CMLogin* msg = (cs::CMLogin*)param.sender.GetUserData();
|
|
PlayerMgr::Instance()->AsyncLoginOnError(
|
|
msg->account_id(),
|
|
2,
|
|
1,
|
|
""
|
|
);
|
|
delete msg;
|
|
};
|
|
cs::CMLogin* msg_copy = new cs::CMLogin();
|
|
*msg_copy = msg;
|
|
a8::XObject conn_info = DBEngine::Instance()->GetConnInfo(msg.account_id());
|
|
DBEngine::Instance()->ExecAsyncQuery
|
|
(conn_info,
|
|
"SELECT account_id, nickname, avatar_url, sex, "
|
|
" data_version1, friend_data, user_value1, user_value2, user_value3 "
|
|
"FROM `user` WHERE account_id='%s';",
|
|
{
|
|
msg.account_id(),
|
|
},
|
|
a8::XParams()
|
|
.SetSender((void*)msg_copy),
|
|
on_ok,
|
|
on_error,
|
|
a8::openssl::Crc32((unsigned char*)msg.account_id().data(),
|
|
msg.account_id().size())
|
|
);
|
|
}
|
|
|
|
void PlayerMgr::AsyncLoginOnOk(const std::string& account_id,
|
|
const std::string& nickname,
|
|
const std::string& avatar_url,
|
|
int sex,
|
|
int data_version1,
|
|
const std::string& friend_data,
|
|
long long user_value1,
|
|
long long user_value2,
|
|
long long user_value3)
|
|
{
|
|
f8::MsgHdr* hdr = GetHdrByAccountId(account_id);
|
|
if (hdr) {
|
|
Player* hum = GetPlayerByAccountId(account_id);
|
|
if (hum) {
|
|
abort();
|
|
}
|
|
hum = GetPlayerBySocket(hdr->socket_handle);
|
|
if (hum) {
|
|
abort();
|
|
}
|
|
{
|
|
hum = new Player();
|
|
hum->socket_handle = hdr->socket_handle;
|
|
hum->myself.base_data.account_id = account_id;
|
|
hum->myself.base_data.nickname = nickname;
|
|
hum->myself.base_data.avatar_url = avatar_url;
|
|
hum->myself.base_data.sex = sex;
|
|
hum->myself.base_data.base_data_version = data_version1;
|
|
hum->myself.base_data.user_value1 = user_value1;
|
|
hum->myself.base_data.user_value2 = user_value2;
|
|
hum->myself.base_data.user_value3 = user_value3;
|
|
hum->myself.base_data.online = true;
|
|
hum->myself.base_data.last_login_time = App::Instance()->nowtime;
|
|
hum->Init();
|
|
{
|
|
ss::MFUserDB user_db;
|
|
user_db.ParseFromString(friend_data);
|
|
hum->Deserialize(user_db);
|
|
}
|
|
socket_hash_[hdr->socket_handle] = hum;
|
|
accountid_hash_[account_id] = hum;
|
|
}
|
|
pending_socket_hash_.erase(hdr->socket_handle);
|
|
pending_account_hash_.erase(account_id);
|
|
{
|
|
cs::SMLogin respmsg;
|
|
respmsg.set_errcode(0);
|
|
respmsg.set_errmsg("ok");
|
|
hum->SendMsg(respmsg);
|
|
}
|
|
f8::MsgHdr::Destroy(hdr);
|
|
}
|
|
}
|
|
|
|
void PlayerMgr::AsyncLoginOnError(const std::string& account_id, int step,
|
|
int error_code, const std::string& error_msg)
|
|
{
|
|
f8::MsgHdr* hdr = GetHdrByAccountId(account_id);
|
|
if (hdr) {
|
|
pending_socket_hash_.erase(hdr->socket_handle);
|
|
pending_account_hash_.erase(account_id);
|
|
f8::MsgHdr::Destroy(hdr);
|
|
}
|
|
}
|
|
|
|
void PlayerMgr::OnClientSocketDisconnect(int socket_handle)
|
|
{
|
|
{
|
|
auto itr = pending_socket_hash_.find(socket_handle);
|
|
if (itr != pending_socket_hash_.end()) {
|
|
pending_account_hash_.erase(std::get<0>(itr->second));
|
|
f8::MsgHdr::Destroy(std::get<1>(itr->second));
|
|
pending_socket_hash_.erase(itr);
|
|
}
|
|
}
|
|
{
|
|
Player* hum = GetPlayerBySocket(socket_handle);
|
|
if (hum) {
|
|
hum->NotifyOffline();
|
|
hum->UnInit();
|
|
socket_hash_.erase(socket_handle);
|
|
accountid_hash_.erase(hum->myself.base_data.account_id);
|
|
}
|
|
}
|
|
#ifdef DEBUG
|
|
a8::UdpLog::Instance()->Debug
|
|
(
|
|
"OnClientSocketDisconnect %d",
|
|
{
|
|
socket_handle
|
|
});
|
|
#endif
|
|
}
|