#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(job); accountTable->players[i].byLevel = static_cast(level); accountTable->players[i].dwPlayMinutes = progressValue; accountTable->players[i].byST = static_cast(st); accountTable->players[i].byHT = static_cast(ht); accountTable->players[i].byDX = static_cast(dx); accountTable->players[i].byIQ = static_cast(iq); accountTable->players[i].wMainPart = static_cast(mainPart); accountTable->players[i].wHairPart = static_cast(hairPart); accountTable->players[i].x = x; accountTable->players[i].y = y; accountTable->players[i].skill_group = static_cast(skillGroup); accountTable->players[i].bChangeName = static_cast(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(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(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)); }