1
This commit is contained in:
parent
7da3452071
commit
1b73729a60
@ -60,7 +60,7 @@ public:
|
|||||||
|
|
||||||
virtual void OnDisConnect() override
|
virtual void OnDisConnect() override
|
||||||
{
|
{
|
||||||
App::Instance()->AddIMMsg(IM_WSProxySocketDisconnect,
|
App::Instance()->AddIMMsg(IM_WSProxyDisconnect,
|
||||||
a8::XParams()
|
a8::XParams()
|
||||||
.SetSender(socket_handle)
|
.SetSender(socket_handle)
|
||||||
.SetParam1(1));
|
.SetParam1(1));
|
||||||
|
@ -206,6 +206,7 @@ int App::Run()
|
|||||||
a8::UdpLog::Instance()->Info("friend_imserver running", {});
|
a8::UdpLog::Instance()->Info("friend_imserver running", {});
|
||||||
while (!terminated) {
|
while (!terminated) {
|
||||||
a8::tick_t begin_tick = a8::XGetTickCount();
|
a8::tick_t begin_tick = a8::XGetTickCount();
|
||||||
|
nowtime = time(nullptr);
|
||||||
QuickExecute();
|
QuickExecute();
|
||||||
SlowerExecute();
|
SlowerExecute();
|
||||||
a8::tick_t end_tick = a8::XGetTickCount();
|
a8::tick_t end_tick = a8::XGetTickCount();
|
||||||
@ -491,12 +492,9 @@ void App::ProcessIMMsg()
|
|||||||
while (im_work_node_) {
|
while (im_work_node_) {
|
||||||
IMMsgNode *pdelnode = im_work_node_;
|
IMMsgNode *pdelnode = im_work_node_;
|
||||||
switch (im_work_node_->msgid) {
|
switch (im_work_node_->msgid) {
|
||||||
case IM_WSProxySocketDisconnect:
|
case IM_WSProxyDisconnect:
|
||||||
{
|
{
|
||||||
#if 0
|
PlayerMgr::Instance()->OnWSProxyDisconnect(pdelnode->params);
|
||||||
GameClientMgr::Instance()->OnClientDisconnect(pdelnode->params);
|
|
||||||
MasterSvrMgr::Instance()->RemoveRequest(pdelnode->params.param1, pdelnode->params.sender, true);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -65,6 +65,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
int instance_id = 0;
|
int instance_id = 0;
|
||||||
|
int nowtime = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::mutex *loop_mutex_ = nullptr;
|
std::mutex *loop_mutex_ = nullptr;
|
||||||
|
@ -10,7 +10,7 @@ enum SocketFrom_e
|
|||||||
|
|
||||||
enum InnerMesssage_e
|
enum InnerMesssage_e
|
||||||
{
|
{
|
||||||
IM_WSProxySocketDisconnect = 100,
|
IM_WSProxyDisconnect = 100,
|
||||||
IM_PlayerOffline,
|
IM_PlayerOffline,
|
||||||
IM_ExecGM,
|
IM_ExecGM,
|
||||||
IM_MasterSvrDisconnect,
|
IM_MasterSvrDisconnect,
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "precompile.h"
|
#include "precompile.h"
|
||||||
|
|
||||||
|
#include <a8/openssl.h>
|
||||||
|
|
||||||
#include "dbengine.h"
|
#include "dbengine.h"
|
||||||
|
|
||||||
void DBEngine::Init()
|
void DBEngine::Init()
|
||||||
@ -51,7 +53,12 @@ void DBEngine::ExecAsyncScript(a8::XObject conn_info,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
a8::XObject DBEngine::GetConnInfoByHash(long long hash_code)
|
a8::XObject DBEngine::GetConnInfo(const std::string& data)
|
||||||
|
{
|
||||||
|
return GetConnInfo(a8::openssl::Crc32((unsigned char*)data.data(), data.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
a8::XObject DBEngine::GetConnInfo(long long data)
|
||||||
{
|
{
|
||||||
a8::XObject conn_info;
|
a8::XObject conn_info;
|
||||||
return conn_info;
|
return conn_info;
|
||||||
|
@ -29,5 +29,6 @@ class DBEngine : public a8::Singleton<DBEngine>
|
|||||||
f8::AsyncDBOnErrorFunc on_error,
|
f8::AsyncDBOnErrorFunc on_error,
|
||||||
long long hash_code = 0);
|
long long hash_code = 0);
|
||||||
|
|
||||||
a8::XObject GetConnInfoByHash(long long hash_code);
|
a8::XObject GetConnInfo(const std::string& data);
|
||||||
|
a8::XObject GetConnInfo(long long data);
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
#include "precompile.h"
|
#include "precompile.h"
|
||||||
|
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
#include "playermgr.h"
|
||||||
|
#include "WSListener.h"
|
||||||
|
|
||||||
void Player::Init()
|
void Player::Init()
|
||||||
{
|
{
|
||||||
|
SyncLocToMasterServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::UnInit()
|
void Player::UnInit()
|
||||||
@ -66,3 +68,16 @@ void Player::_CMGroupRename(f8::MsgHdr& hdr, const cs::CMGroupRename& msg)
|
|||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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::SyncLocToMasterServer()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -9,6 +9,11 @@ class Player
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
int socket_handle = 0;
|
int socket_handle = 0;
|
||||||
|
std::string account_id;
|
||||||
|
std::string nickname;
|
||||||
|
std::string avatar_url;
|
||||||
|
int sex = 0;
|
||||||
|
long long group_id = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init();
|
void Init();
|
||||||
@ -26,4 +31,7 @@ class Player
|
|||||||
void _CMGroupQuit(f8::MsgHdr& hdr, const cs::CMGroupQuit& msg);
|
void _CMGroupQuit(f8::MsgHdr& hdr, const cs::CMGroupQuit& msg);
|
||||||
void _CMGroupDismiss(f8::MsgHdr& hdr, const cs::CMGroupDismiss& msg);
|
void _CMGroupDismiss(f8::MsgHdr& hdr, const cs::CMGroupDismiss& msg);
|
||||||
void _CMGroupRename(f8::MsgHdr& hdr, const cs::CMGroupRename& msg);
|
void _CMGroupRename(f8::MsgHdr& hdr, const cs::CMGroupRename& msg);
|
||||||
|
|
||||||
|
void ReLogin(f8::MsgHdr& hdr, const cs::CMLogin& msg);
|
||||||
|
void SyncLocToMasterServer();
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
#include "precompile.h"
|
#include "precompile.h"
|
||||||
|
|
||||||
|
#include <a8/openssl.h>
|
||||||
|
|
||||||
#include "playermgr.h"
|
#include "playermgr.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "cs_proto.pb.h"
|
#include "cs_proto.pb.h"
|
||||||
#include "dbengine.h"
|
#include "dbengine.h"
|
||||||
|
#include "WSListener.h"
|
||||||
|
#include "app.h"
|
||||||
|
|
||||||
#include "framework/cpp/utils.h"
|
#include "framework/cpp/utils.h"
|
||||||
|
|
||||||
@ -17,10 +21,7 @@ void PlayerMgr::UnInit()
|
|||||||
|
|
||||||
void PlayerMgr::_SS_WSP_SocketDisconnect(f8::MsgHdr& hdr, const ss::SS_WSP_SocketDisconnect& msg)
|
void PlayerMgr::_SS_WSP_SocketDisconnect(f8::MsgHdr& hdr, const ss::SS_WSP_SocketDisconnect& msg)
|
||||||
{
|
{
|
||||||
Player* hum = GetPlayerBySocket(hdr.socket_handle);
|
OnClientSocketDisconnect(hdr.socket_handle);
|
||||||
if (hum) {
|
|
||||||
RemovePlayerBySocket(hdr.socket_handle);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerMgr::_SS_MS_PushUserList(f8::MsgHdr& hdr, const ss::SS_MS_PushUserList& msg)
|
void PlayerMgr::_SS_MS_PushUserList(f8::MsgHdr& hdr, const ss::SS_MS_PushUserList& msg)
|
||||||
@ -37,9 +38,20 @@ void PlayerMgr::_CMLogin(f8::MsgHdr& hdr, const cs::CMLogin& msg)
|
|||||||
{
|
{
|
||||||
Player* hum = GetPlayerByAccountId(msg.account_id());
|
Player* hum = GetPlayerByAccountId(msg.account_id());
|
||||||
if (hum) {
|
if (hum) {
|
||||||
|
hum->ReLogin(hdr, msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (GetHdrBySocket(hdr.socket_handle) ||
|
||||||
|
GetHdrByAccountId(msg.account_id())) {
|
||||||
|
cs::SMLogin respmsg;
|
||||||
|
respmsg.set_error_code(1);
|
||||||
|
WSListener::Instance()->SendToClient(hdr.socket_handle, 0, respmsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
f8::MsgHdr* new_hdr = hdr.Clone();
|
||||||
|
pending_socket_hash_[hdr.socket_handle] = new_hdr;
|
||||||
|
pending_account_hash_[msg.account_id()] = new_hdr;
|
||||||
|
AsyncLogin1(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int PlayerMgr::OnlineNum()
|
int PlayerMgr::OnlineNum()
|
||||||
@ -59,6 +71,29 @@ Player* PlayerMgr::GetPlayerByAccountId(const std::string& account_id)
|
|||||||
return itr != accountid_hash_.end() ? itr->second : nullptr;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PlayerMgr::OnClientDisconnect(a8::XParams& param)
|
void PlayerMgr::OnClientDisconnect(a8::XParams& param)
|
||||||
{
|
{
|
||||||
int gg_socket = param.sender;
|
int gg_socket = param.sender;
|
||||||
@ -86,3 +121,191 @@ void PlayerMgr::RemovePlayerBySocket(int socket_handle)
|
|||||||
socket_hash_.erase(itr);
|
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() ? 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, group_id, createtime, modifytime, registertime)"
|
||||||
|
"VALUES ('%s', '%s', '%s', %d, 0, %d, %d, %d)"
|
||||||
|
"ON DUPLICATE KEY UPDATE nickname='%s', avatar_url='%s',"
|
||||||
|
" sex=%d, last_logintime=%d;",
|
||||||
|
{
|
||||||
|
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),
|
||||||
|
data_set->at(0).at(1),
|
||||||
|
data_set->at(0).at(2),
|
||||||
|
a8::XValue(data_set->at(0).at(3)),
|
||||||
|
a8::XValue(data_set->at(0).at(4))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
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, group_id "
|
||||||
|
"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,
|
||||||
|
long long group_id)
|
||||||
|
{
|
||||||
|
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->account_id = account_id;
|
||||||
|
hum->nickname = nickname;
|
||||||
|
hum->avatar_url = avatar_url;
|
||||||
|
hum->sex = sex;
|
||||||
|
hum->group_id = group_id;
|
||||||
|
hum->Init();
|
||||||
|
socket_hash_[hdr->socket_handle] = hum;
|
||||||
|
accountid_hash_[account_id] = hum;
|
||||||
|
}
|
||||||
|
pending_socket_hash_.erase(hdr->socket_handle);
|
||||||
|
pending_account_hash_.erase(account_id);
|
||||||
|
if (hdr->buf) {
|
||||||
|
free((void*)hdr->buf);
|
||||||
|
}
|
||||||
|
free((void*)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);
|
||||||
|
if (hdr->buf) {
|
||||||
|
free((void*)hdr->buf);
|
||||||
|
}
|
||||||
|
free((void*)hdr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerMgr::OnClientSocketDisconnect(int socket_handle)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
f8::MsgHdr* hdr = GetHdrBySocket(socket_handle);
|
||||||
|
if (hdr) {
|
||||||
|
if (hdr->buf) {
|
||||||
|
free((void*)hdr->buf);
|
||||||
|
}
|
||||||
|
free((void*)hdr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Player* hum = GetPlayerBySocket(socket_handle);
|
||||||
|
if (hum) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -34,13 +34,32 @@ class PlayerMgr : public a8::Singleton<PlayerMgr>
|
|||||||
|
|
||||||
Player* GetPlayerBySocket(int socket);
|
Player* GetPlayerBySocket(int socket);
|
||||||
Player* GetPlayerByAccountId(const std::string& account_id);
|
Player* GetPlayerByAccountId(const std::string& account_id);
|
||||||
|
void ReBindSocket(int socket_handle, Player* hum);
|
||||||
|
void OnWSProxyDisconnect(a8::XParams& param);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int OnlineNum();
|
int OnlineNum();
|
||||||
void OnClientDisconnect(a8::XParams& param);
|
void OnClientDisconnect(a8::XParams& param);
|
||||||
void RemovePlayerBySocket(int socket_handle);
|
void RemovePlayerBySocket(int socket_handle);
|
||||||
|
f8::MsgHdr* GetHdrBySocket(int socket_handle);
|
||||||
|
f8::MsgHdr* GetHdrByAccountId(const std::string& account_id);
|
||||||
|
void AsyncLogin1(const cs::CMLogin& msg);
|
||||||
|
void AsyncLogin2(const cs::CMLogin& msg);
|
||||||
|
void AsyncLoginOnOk(const std::string& account_id,
|
||||||
|
const std::string& nickname,
|
||||||
|
const std::string& avatar_url,
|
||||||
|
int sex,
|
||||||
|
long long group_id);
|
||||||
|
void AsyncLoginOnError(const std::string& account_id,
|
||||||
|
int step,
|
||||||
|
int error_code,
|
||||||
|
const std::string& error_msg);
|
||||||
|
void OnClientSocketDisconnect(int socket_handle);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<int, Player*> socket_hash_;
|
std::map<int, Player*> socket_hash_;
|
||||||
std::map<std::string, Player*> accountid_hash_;
|
std::map<std::string, Player*> accountid_hash_;
|
||||||
|
|
||||||
|
std::map<int, f8::MsgHdr*> pending_socket_hash_;
|
||||||
|
std::map<std::string, f8::MsgHdr*> pending_account_hash_;
|
||||||
};
|
};
|
||||||
|
@ -35,6 +35,8 @@ message CMLogin
|
|||||||
}
|
}
|
||||||
message SMLogin
|
message SMLogin
|
||||||
{
|
{
|
||||||
|
optional int32 error_code = 1;
|
||||||
|
optional string error_msg = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CMFriendList
|
message CMFriendList
|
||||||
|
@ -46,6 +46,7 @@ CREATE TABLE `user` (
|
|||||||
`createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
`createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
`modifytime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间',
|
`modifytime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间',
|
||||||
`registertime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
`registertime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
|
`last_logintime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
|
||||||
PRIMARY KEY (`idx`),
|
PRIMARY KEY (`idx`),
|
||||||
UNIQUE KEY `account_id` (`account_id`),
|
UNIQUE KEY `account_id` (`account_id`),
|
||||||
KEY `nickname` (`nickname`),
|
KEY `nickname` (`nickname`),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user