Files
m2dev-server-src/src/db/ClientManagerLogin.cpp
2026-04-13 22:47:06 +02:00

742 lines
22 KiB
C++

#include "stdafx.h"
#include "ClientManager.h"
#include "Main.h"
#include "Config.h"
#include "QID.h"
#include "Cache.h"
#include "libsql/Statement.h"
extern std::string g_stLocale;
extern bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab);
extern int g_test_server;
extern int g_log;
namespace
{
bool PreparePlayerStmt(CStmt& stmt, const std::string& query)
{
CAsyncSQL* sql = CDBManager::instance().GetDirectSQL(SQL_PLAYER);
if (!sql)
{
sys_err("player SQL handle is not initialized");
return false;
}
return stmt.Prepare(sql, query.c_str());
}
bool LoadPlayerIndexTable(uint32_t accountId, TAccountTable* accountTable)
{
CStmt stmt;
const std::string query = std::string("SELECT pid1, pid2, pid3, pid4, empire FROM player_index") + GetTablePostfix() + " WHERE id=?";
uint32_t playerIds[PLAYER_PER_ACCOUNT] = {};
uint8_t empire = 0;
if (!PreparePlayerStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_LONG, &accountId))
return false;
for (int i = 0; i < PLAYER_PER_ACCOUNT; ++i)
{
if (!stmt.BindResult(MYSQL_TYPE_LONG, &playerIds[i]))
return false;
}
if (!stmt.BindResult(MYSQL_TYPE_TINY, &empire))
return false;
if (!stmt.Execute() || !stmt.Fetch())
return false;
for (int i = 0; i < PLAYER_PER_ACCOUNT; ++i)
accountTable->players[i].dwID = playerIds[i];
accountTable->bEmpire = empire;
return true;
}
bool CreatePlayerIndexRow(uint32_t accountId)
{
CStmt stmt;
const std::string query = std::string("INSERT INTO player_index") + GetTablePostfix() + " (id) VALUES(?)";
if (!PreparePlayerStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_LONG, &accountId))
return false;
return stmt.Execute();
}
void ApplyPlayerSummary(TAccountTable* accountTable, uint32_t playerId, const char* name, uint32_t job, uint32_t level, uint32_t progressValue,
int32_t st, int32_t ht, int32_t dx, int32_t iq, uint32_t mainPart, uint32_t hairPart, int32_t x, int32_t y, uint32_t skillGroup, uint32_t changeName)
{
for (int i = 0; i < PLAYER_PER_ACCOUNT; ++i)
{
if (accountTable->players[i].dwID != playerId)
continue;
CPlayerTableCache* cache = CClientManager::instance().GetPlayerCache(playerId);
TPlayerTable* playerTable = cache ? cache->Get(false) : NULL;
if (playerTable)
{
strlcpy(accountTable->players[i].szName, playerTable->name, sizeof(accountTable->players[i].szName));
accountTable->players[i].byJob = playerTable->job;
accountTable->players[i].byLevel = playerTable->level;
accountTable->players[i].dwPlayMinutes = playerTable->playtime;
accountTable->players[i].byST = playerTable->st;
accountTable->players[i].byHT = playerTable->ht;
accountTable->players[i].byDX = playerTable->dx;
accountTable->players[i].byIQ = playerTable->iq;
accountTable->players[i].wMainPart = playerTable->parts[PART_MAIN];
accountTable->players[i].wHairPart = playerTable->parts[PART_HAIR];
accountTable->players[i].x = playerTable->x;
accountTable->players[i].y = playerTable->y;
accountTable->players[i].skill_group = playerTable->skill_group;
accountTable->players[i].bChangeName = 0;
}
else
{
strlcpy(accountTable->players[i].szName, name, sizeof(accountTable->players[i].szName));
accountTable->players[i].byJob = static_cast<uint8_t>(job);
accountTable->players[i].byLevel = static_cast<uint8_t>(level);
accountTable->players[i].dwPlayMinutes = progressValue;
accountTable->players[i].byST = static_cast<uint8_t>(st);
accountTable->players[i].byHT = static_cast<uint8_t>(ht);
accountTable->players[i].byDX = static_cast<uint8_t>(dx);
accountTable->players[i].byIQ = static_cast<uint8_t>(iq);
accountTable->players[i].wMainPart = static_cast<uint16_t>(mainPart);
accountTable->players[i].wHairPart = static_cast<uint16_t>(hairPart);
accountTable->players[i].x = x;
accountTable->players[i].y = y;
accountTable->players[i].skill_group = static_cast<uint8_t>(skillGroup);
accountTable->players[i].bChangeName = static_cast<uint8_t>(changeName);
}
sys_log(0, "%s %lu %lu hair %u",
accountTable->players[i].szName,
accountTable->players[i].x,
accountTable->players[i].y,
accountTable->players[i].wHairPart);
return;
}
}
bool LoadAccountPlayerSummaries(uint32_t accountId, TAccountTable* accountTable)
{
CStmt stmt;
std::string query;
uint32_t playerId = 0;
char name[CHARACTER_NAME_MAX_LEN + 1] = {};
uint32_t job = 0;
uint32_t level = 0;
uint32_t progressValue = 0;
int32_t st = 0;
int32_t ht = 0;
int32_t dx = 0;
int32_t iq = 0;
uint32_t mainPart = 0;
uint32_t hairPart = 0;
int32_t x = 0;
int32_t y = 0;
uint32_t skillGroup = 0;
uint32_t changeName = 0;
if (g_stLocale == "gb2312")
{
query = std::string("SELECT id, name, job, level, alignment, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player")
+ GetTablePostfix() + " WHERE account_id=?";
}
else
{
query = std::string("SELECT id, name, job, level, playtime, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player")
+ GetTablePostfix() + " WHERE account_id=?";
}
if (!PreparePlayerStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_LONG, &accountId))
return false;
if (!stmt.BindResult(MYSQL_TYPE_LONG, &playerId)
|| !stmt.BindResult(MYSQL_TYPE_STRING, name, sizeof(name))
|| !stmt.BindResult(MYSQL_TYPE_LONG, &job)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &level)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &progressValue)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &st)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &ht)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &dx)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &iq)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &mainPart)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &hairPart)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &x)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &y)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &skillGroup)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &changeName))
{
return false;
}
if (!stmt.Execute())
return false;
while (stmt.Fetch())
{
size_t nameLen = stmt.GetResultLength(1);
if (nameLen >= sizeof(name))
nameLen = sizeof(name) - 1;
name[nameLen] = '\0';
ApplyPlayerSummary(accountTable, playerId, name, job, level, progressValue, st, ht, dx, iq, mainPart, hairPart, x, y, skillGroup, changeName);
}
return true;
}
bool CountPlayerNames(const char* playerName, uint32_t playerId, uint32_t* count)
{
CStmt stmt;
std::string query;
if (g_stLocale == "sjis")
query = std::string("SELECT COUNT(*) FROM player") + GetTablePostfix() + " WHERE name=? collate sjis_japanese_ci AND id <> ?";
else
query = std::string("SELECT COUNT(*) FROM player") + GetTablePostfix() + " WHERE name=? AND id <> ?";
if (!PreparePlayerStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_STRING, const_cast<char*>(playerName), CHARACTER_NAME_MAX_LEN + 1)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &playerId)
|| !stmt.BindResult(MYSQL_TYPE_LONG, count))
{
return false;
}
return stmt.Execute() && stmt.Fetch();
}
bool UpdatePlayerName(uint32_t playerId, const char* playerName)
{
CStmt stmt;
const std::string query = std::string("UPDATE player") + GetTablePostfix() + " SET name=?, change_name=0 WHERE id=?";
if (!PreparePlayerStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_STRING, const_cast<char*>(playerName), CHARACTER_NAME_MAX_LEN + 1)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &playerId))
{
return false;
}
return stmt.Execute();
}
}
bool CClientManager::InsertLogonAccount(const char * c_pszLogin, DWORD dwHandle, const char * c_pszIP)
{
char szLogin[LOGIN_MAX_LEN + 1];
trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin));
itertype(m_map_kLogonAccount) it = m_map_kLogonAccount.find(szLogin);
if (m_map_kLogonAccount.end() != it)
return false;
CLoginData * pkLD = GetLoginDataByLogin(c_pszLogin);
if (!pkLD)
return false;
pkLD->SetConnectedPeerHandle(dwHandle);
pkLD->SetIP(c_pszIP);
m_map_kLogonAccount.insert(TLogonAccountMap::value_type(szLogin, pkLD));
return true;
}
bool CClientManager::DeleteLogonAccount(const char * c_pszLogin, DWORD dwHandle)
{
char szLogin[LOGIN_MAX_LEN + 1];
trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin));
itertype(m_map_kLogonAccount) it = m_map_kLogonAccount.find(szLogin);
if (it == m_map_kLogonAccount.end())
return false;
CLoginData * pkLD = it->second;
if (pkLD->GetConnectedPeerHandle() != dwHandle)
{
sys_err("%s tried to logout in other peer handle %lu, current handle %lu", szLogin, dwHandle, pkLD->GetConnectedPeerHandle());
return false;
}
if (pkLD->IsPlay())
{
pkLD->SetPlay(false);
}
if (pkLD->IsDeleted())
{
delete pkLD;
}
m_map_kLogonAccount.erase(it);
return true;
}
bool CClientManager::FindLogonAccount(const char * c_pszLogin)
{
char szLogin[LOGIN_MAX_LEN + 1];
trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin));
if (m_map_kLogonAccount.end() == m_map_kLogonAccount.find(szLogin))
return false;
return true;
}
void CClientManager::QUERY_LOGIN_BY_KEY(CPeer * pkPeer, DWORD dwHandle, TPacketGDLoginByKey * p)
{
CLoginData * pkLoginData = GetLoginData(p->dwLoginKey);
char szLogin[LOGIN_MAX_LEN + 1];
trim_and_lower(p->szLogin, szLogin, sizeof(szLogin));
if (!pkLoginData)
{
sys_log(0, "LOGIN_BY_KEY key not exist %s %lu", szLogin, p->dwLoginKey);
pkPeer->EncodeReturn(DG::LOGIN_NOT_EXIST, dwHandle);
return;
}
TAccountTable & r = pkLoginData->GetAccountRef();
if (FindLogonAccount(r.login))
{
sys_log(0, "LOGIN_BY_KEY already login %s %lu", r.login, p->dwLoginKey);
TPacketDGLoginAlready ptog;
strlcpy(ptog.szLogin, r.login, sizeof(ptog.szLogin));
pkPeer->EncodeHeader(DG::LOGIN_ALREADY, dwHandle, sizeof(TPacketDGLoginAlready));
pkPeer->Encode(&ptog, sizeof(TPacketDGLoginAlready));
return;
}
if (strcasecmp(r.login, szLogin))
{
sys_log(0, "LOGIN_BY_KEY login differ %s %lu input %s", r.login, p->dwLoginKey, szLogin);
pkPeer->EncodeReturn(DG::LOGIN_NOT_EXIST, dwHandle);
return;
}
TAccountTable accountTable = {};
accountTable.id = r.id;
trim_and_lower(r.login, accountTable.login, sizeof(accountTable.login));
strlcpy(accountTable.passwd, r.passwd, sizeof(accountTable.passwd));
strlcpy(accountTable.social_id, r.social_id, sizeof(accountTable.social_id));
strlcpy(accountTable.status, "OK", sizeof(accountTable.status));
sys_log(0, "LOGIN_BY_KEY success %s %lu %s", r.login, p->dwLoginKey, p->szIP);
if (!LoadPlayerIndexTable(accountTable.id, &accountTable))
{
sys_log(0, "LOGIN_BY_KEY missing player_index for account %u", accountTable.id);
CreatePlayerIndexRow(accountTable.id);
if (!LoadPlayerIndexTable(accountTable.id, &accountTable))
{
pkPeer->EncodeReturn(DG::LOGIN_NOT_EXIST, dwHandle);
return;
}
}
if (!LoadAccountPlayerSummaries(accountTable.id, &accountTable))
{
pkPeer->EncodeReturn(DG::LOGIN_NOT_EXIST, dwHandle);
return;
}
if (!InsertLogonAccount(accountTable.login, pkPeer->GetHandle(), p->szIP))
{
sys_log(0, "RESULT_LOGIN: already logon %s", accountTable.login);
TPacketDGLoginAlready packet;
strlcpy(packet.szLogin, accountTable.login, sizeof(packet.szLogin));
pkPeer->EncodeHeader(DG::LOGIN_ALREADY, dwHandle, sizeof(TPacketDGLoginAlready));
pkPeer->Encode(&packet, sizeof(packet));
return;
}
if (CLoginData* loginData = GetLoginDataByLogin(accountTable.login))
memcpy(&loginData->GetAccountRef(), &accountTable, sizeof(TAccountTable));
pkPeer->EncodeHeader(DG::LOGIN_SUCCESS, dwHandle, sizeof(TAccountTable));
pkPeer->Encode(&accountTable, sizeof(TAccountTable));
}
void CClientManager::RESULT_LOGIN_BY_KEY(CPeer * peer, SQLMsg * msg)
{
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData;
if (msg->uiSQLErrno != 0)
{
peer->EncodeReturn(DG::LOGIN_NOT_EXIST, info->dwHandle);
delete info;
return;
}
char szQuery[QUERY_MAX_LEN];
if (msg->Get()->uiNumRows == 0)
{
DWORD account_id = info->pAccountTable->id;
sys_log(0, "RESULT_LOGIN_BY_KEY FAIL player_index's NULL : ID:%d", account_id);
// PLAYER_INDEX_CREATE_BUG_FIX
snprintf(szQuery, sizeof(szQuery), "INSERT INTO player_index%s (id) VALUES(%u)", GetTablePostfix(), info->pAccountTable->id);
CDBManager::instance().ReturnQuery(szQuery, QID_PLAYER_INDEX_CREATE, peer->GetHandle(), info);
// END_PLAYER_INDEX_CREATE_BUF_FIX
return;
}
MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult);
int col = 0;
for (; col < PLAYER_PER_ACCOUNT; ++col)
str_to_number(info->pAccountTable->players[col].dwID, row[col]);
str_to_number(info->pAccountTable->bEmpire, row[col++]);
info->account_index = 1;
extern std::string g_stLocale;
if (g_stLocale == "gb2312")
{
snprintf(szQuery, sizeof(szQuery),
"SELECT id, name, job, level, alignment, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player%s WHERE account_id=%u",
GetTablePostfix(), info->pAccountTable->id);
}
else
{
snprintf(szQuery, sizeof(szQuery),
"SELECT id, name, job, level, playtime, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player%s WHERE account_id=%u",
GetTablePostfix(), info->pAccountTable->id);
}
CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN, peer->GetHandle(), info);
}
// PLAYER_INDEX_CREATE_BUG_FIX
void CClientManager::RESULT_PLAYER_INDEX_CREATE(CPeer * pkPeer, SQLMsg * msg)
{
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData;
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(),
info->pAccountTable->id);
CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info);
}
// END_PLAYER_INDEX_CREATE_BUG_FIX
TAccountTable * CreateAccountTableFromRes(MYSQL_RES * res)
{
char input_pwd[PASSWD_MAX_LEN + 1];
MYSQL_ROW row = NULL;
DWORD col;
row = mysql_fetch_row(res);
col = 0;
TAccountTable * pkTab = new TAccountTable;
memset(pkTab, 0, sizeof(TAccountTable));
// 첫번째 컬럼 것만 참고 한다 (JOIN QUERY를 위한 것 임)
strlcpy(input_pwd, row[col++], sizeof(input_pwd));
str_to_number(pkTab->id, row[col++]);
strlcpy(pkTab->login, row[col++], sizeof(pkTab->login));
strlcpy(pkTab->passwd, row[col++], sizeof(pkTab->passwd));
strlcpy(pkTab->social_id, row[col++], sizeof(pkTab->social_id));
str_to_number(pkTab->bEmpire, row[col++]);
for (int j = 0; j < PLAYER_PER_ACCOUNT; ++j)
str_to_number(pkTab->players[j].dwID, row[col++]);
strlcpy(pkTab->status, row[col++], sizeof(pkTab->status));
if (strcmp(pkTab->passwd, input_pwd))
{
delete pkTab;
return NULL;
}
return pkTab;
}
void CreateAccountPlayerDataFromRes(MYSQL_RES * pRes, TAccountTable * pkTab)
{
if (!pRes)
return;
for (DWORD i = 0; i < mysql_num_rows(pRes); ++i)
{
MYSQL_ROW row = mysql_fetch_row(pRes);
int col = 0;
DWORD player_id = 0;
!row[col++] ? 0 : str_to_number(player_id, row[col - 1]);
if (!player_id)
continue;
int j;
for (j = 0; j < PLAYER_PER_ACCOUNT; ++j)
{
if (pkTab->players[j].dwID == player_id)
{
CPlayerTableCache * pc = CClientManager::instance().GetPlayerCache(player_id);
TPlayerTable * pt = pc ? pc->Get(false) : NULL;
if (pt)
{
strlcpy(pkTab->players[j].szName, pt->name, sizeof(pkTab->players[j].szName));
pkTab->players[j].byJob = pt->job;
pkTab->players[j].byLevel = pt->level;
pkTab->players[j].dwPlayMinutes = pt->playtime;
pkTab->players[j].byST = pt->st;
pkTab->players[j].byHT = pt->ht;
pkTab->players[j].byDX = pt->dx;
pkTab->players[j].byIQ = pt->iq;
pkTab->players[j].wMainPart = pt->parts[PART_MAIN];
pkTab->players[j].wHairPart = pt->parts[PART_HAIR];
pkTab->players[j].x = pt->x;
pkTab->players[j].y = pt->y;
pkTab->players[j].skill_group = pt->skill_group;
pkTab->players[j].bChangeName = 0;
}
else
{
if (!row[col++])
*pkTab->players[j].szName = '\0';
else
strlcpy(pkTab->players[j].szName, row[col - 1], sizeof(pkTab->players[j].szName));
pkTab->players[j].byJob = 0;
pkTab->players[j].byLevel = 0;
pkTab->players[j].dwPlayMinutes = 0;
pkTab->players[j].byST = 0;
pkTab->players[j].byHT = 0;
pkTab->players[j].byDX = 0;
pkTab->players[j].byIQ = 0;
pkTab->players[j].wMainPart = 0;
pkTab->players[j].wHairPart = 0;
pkTab->players[j].x = 0;
pkTab->players[j].y = 0;
pkTab->players[j].skill_group = 0;
pkTab->players[j].bChangeName = 0;
str_to_number(pkTab->players[j].byJob, row[col++]);
str_to_number(pkTab->players[j].byLevel, row[col++]);
str_to_number(pkTab->players[j].dwPlayMinutes, row[col++]);
str_to_number(pkTab->players[j].byST, row[col++]);
str_to_number(pkTab->players[j].byHT, row[col++]);
str_to_number(pkTab->players[j].byDX, row[col++]);
str_to_number(pkTab->players[j].byIQ, row[col++]);
str_to_number(pkTab->players[j].wMainPart, row[col++]);
str_to_number(pkTab->players[j].wHairPart, row[col++]);
str_to_number(pkTab->players[j].x, row[col++]);
str_to_number(pkTab->players[j].y, row[col++]);
str_to_number(pkTab->players[j].skill_group, row[col++]);
str_to_number(pkTab->players[j].bChangeName, row[col++]);
}
sys_log(0, "%s %lu %lu hair %u",
pkTab->players[j].szName, pkTab->players[j].x, pkTab->players[j].y, pkTab->players[j].wHairPart);
break;
}
}
/*
if (j == PLAYER_PER_ACCOUNT)
sys_err("cannot find player_id on this account (login: %s id %lu account %lu %lu %lu)",
pkTab->login, player_id,
pkTab->players[0].dwID,
pkTab->players[1].dwID,
pkTab->players[2].dwID);
*/
}
}
void CClientManager::RESULT_LOGIN(CPeer * peer, SQLMsg * msg)
{
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData;
if (info->account_index == 0)
{
// 계정이 없네?
if (msg->Get()->uiNumRows == 0)
{
sys_log(0, "RESULT_LOGIN: no account");
peer->EncodeHeader(DG::LOGIN_NOT_EXIST, info->dwHandle, 0);
delete info;
return;
}
info->pAccountTable = CreateAccountTableFromRes(msg->Get()->pSQLResult);
if (!info->pAccountTable)
{
sys_log(0, "RESULT_LOGIN: no account : WRONG_PASSWD");
peer->EncodeReturn(DG::LOGIN_WRONG_PASSWD, info->dwHandle);
delete info;
}
else
{
++info->account_index;
char queryStr[512];
extern std::string g_stLocale;
if (g_stLocale == "gb2312")
{
snprintf(queryStr, sizeof(queryStr),
"SELECT id, name, job, level, alignment, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player%s WHERE account_id=%u",
GetTablePostfix(), info->pAccountTable->id);
}
else
{
snprintf(queryStr, sizeof(queryStr),
"SELECT id, name, job, level, playtime, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player%s WHERE account_id=%u",
GetTablePostfix(), info->pAccountTable->id);
}
CDBManager::instance().ReturnQuery(queryStr, QID_LOGIN, peer->GetHandle(), info);
}
return;
}
else
{
if (!info->pAccountTable) // 이럴리는 없겠지만;;
{
peer->EncodeReturn(DG::LOGIN_WRONG_PASSWD, info->dwHandle);
delete info;
return;
}
// 다른 컨넥션이 이미 로그인 해버렸다면.. 이미 접속했다고 보내야 한다.
if (!InsertLogonAccount(info->pAccountTable->login, peer->GetHandle(), info->ip))
{
sys_log(0, "RESULT_LOGIN: already logon %s", info->pAccountTable->login);
TPacketDGLoginAlready p;
strlcpy(p.szLogin, info->pAccountTable->login, sizeof(p.szLogin));
peer->EncodeHeader(DG::LOGIN_ALREADY, info->dwHandle, sizeof(TPacketDGLoginAlready));
peer->Encode(&p, sizeof(p));
}
else
{
sys_log(0, "RESULT_LOGIN: login success %s rows: %lu", info->pAccountTable->login, msg->Get()->uiNumRows);
if (msg->Get()->uiNumRows > 0)
CreateAccountPlayerDataFromRes(msg->Get()->pSQLResult, info->pAccountTable);
//PREVENT_COPY_ITEM
CLoginData * p = GetLoginDataByLogin(info->pAccountTable->login);
memcpy(&p->GetAccountRef(), info->pAccountTable, sizeof(TAccountTable));
//END_PREVENT_COPY_ITEM
peer->EncodeHeader(DG::LOGIN_SUCCESS, info->dwHandle, sizeof(TAccountTable));
peer->Encode(info->pAccountTable, sizeof(TAccountTable));
}
delete info->pAccountTable;
info->pAccountTable = NULL;
delete info;
}
}
void CClientManager::QUERY_LOGOUT(CPeer * peer, DWORD dwHandle,const char * data)
{
TLogoutPacket* packet = (TLogoutPacket*)data;
if (!*packet->login)
return;
CLoginData * pLoginData = GetLoginDataByLogin(packet->login);
if (pLoginData == NULL)
return;
int pid[PLAYER_PER_ACCOUNT];
for (int n = 0; n < PLAYER_PER_ACCOUNT; ++n)
{
if (pLoginData->GetAccountRef().players[n].dwID == 0)
{
if (g_test_server)
sys_log(0, "LOGOUT %s %d", packet->login, pLoginData->GetAccountRef().players[n].dwID);
continue;
}
pid[n] = pLoginData->GetAccountRef().players[n].dwID;
if (g_log)
sys_log(0, "LOGOUT InsertLogoutPlayer %s %d", packet->login, pid[n]);
InsertLogoutPlayer(pid[n]);
}
if (DeleteLogonAccount(packet->login, peer->GetHandle()))
{
if (g_log)
sys_log(0, "LOGOUT %s ", packet->login);
}
}
void CClientManager::QUERY_CHANGE_NAME(CPeer * peer, DWORD dwHandle, TPacketGDChangeName * p)
{
uint32_t duplicateCount = 0;
if (!CountPlayerNames(p->name, p->pid, &duplicateCount))
{
peer->EncodeHeader(DG::PLAYER_CREATE_FAILED, dwHandle, 0);
return;
}
if (duplicateCount != 0)
{
peer->EncodeHeader(DG::PLAYER_CREATE_ALREADY, dwHandle, 0);
return;
}
if (!UpdatePlayerName(p->pid, p->name))
{
peer->EncodeHeader(DG::PLAYER_CREATE_FAILED, dwHandle, 0);
return;
}
TPacketDGChangeName pdg;
peer->EncodeHeader(DG::CHANGE_NAME, dwHandle, sizeof(TPacketDGChangeName));
pdg.pid = p->pid;
strlcpy(pdg.name, p->name, sizeof(pdg.name));
peer->Encode(&pdg, sizeof(TPacketDGChangeName));
}