db: prepare highscore register flow

This commit is contained in:
server
2026-04-13 23:42:49 +02:00
parent 741da38c8d
commit 4cc8efaac8
3 changed files with 67 additions and 65 deletions

View File

@@ -2710,11 +2710,6 @@ int CClientManager::AnalyzeQueryResult(SQLMsg * msg)
RESULT_SAFEBOX_CHANGE_PASSWORD_SECOND(peer, msg);
break;
case QID_HIGHSCORE_REGISTER:
sys_log(0, "QUERY_RESULT: GD::HIGHSCORE_REGISTER %p", msg);
RESULT_HIGHSCORE_REGISTER(peer, msg);
break;
case QID_SAFEBOX_SAVE:
case QID_ITEM_SAVE:
case QID_ITEM_DESTROY:

View File

@@ -299,7 +299,6 @@ class CClientManager : public CNetBase, public singleton<CClientManager>
void SendPartyOnSetup(CPeer * peer);
void QUERY_HIGHSCORE_REGISTER(CPeer * peer, TPacketGDHighscore* data);
void RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg);
void QUERY_FLUSH_CACHE(CPeer * pkPeer, const char * c_pData);

View File

@@ -30,6 +30,57 @@ namespace
return stmt.Prepare(sql, query.c_str());
}
bool LoadHighscoreValue(const char* board, uint32_t playerId, int& value, bool& found)
{
CStmt stmt;
const std::string query =
"SELECT value FROM highscore" + std::string(GetTablePostfix()) + " WHERE board=? AND pid=?";
found = false;
value = 0;
if (!PreparePlayerStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_STRING, const_cast<char*>(board))
|| !stmt.BindParam(MYSQL_TYPE_LONG, &playerId)
|| !stmt.BindResult(MYSQL_TYPE_LONG, &value))
{
return false;
}
if (!stmt.Execute())
return false;
if (stmt.iRows == 0)
return true;
if (!stmt.Fetch())
return false;
found = true;
return true;
}
bool WriteHighscoreValue(const char* board, uint32_t playerId, int value, bool replaceExisting)
{
CStmt stmt;
const std::string query = std::string(replaceExisting ? "REPLACE INTO highscore" : "INSERT INTO highscore")
+ std::string(GetTablePostfix()) + " (board, pid, value) VALUES(?, ?, ?)";
if (!PreparePlayerStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_STRING, const_cast<char*>(board))
|| !stmt.BindParam(MYSQL_TYPE_LONG, &playerId)
|| !stmt.BindParam(MYSQL_TYPE_LONG, &value))
{
return false;
}
return stmt.Execute();
}
}
//
@@ -1272,73 +1323,30 @@ void CClientManager::QUERY_REMOVE_AFFECT(CPeer * peer, TPacketGDRemoveAffect * p
void CClientManager::QUERY_HIGHSCORE_REGISTER(CPeer* peer, TPacketGDHighscore * data)
{
char szQuery[128];
const std::string escapedBoard = CDBManager::instance().EscapeStringCopy(data->szBoard, strnlen(data->szBoard, sizeof(data->szBoard)));
snprintf(szQuery, sizeof(szQuery), "SELECT value FROM highscore%s WHERE board='%s' AND pid = %u", GetTablePostfix(), escapedBoard.c_str(), data->dwPID);
(void)peer;
sys_log(0, "GD::HIGHSCORE_REGISTER: PID %u", data->dwPID);
char board[sizeof(data->szBoard)];
int currentValue = 0;
bool found = false;
const bool higherIsBetter = data->cDir > 0;
const int value = static_cast<int>(data->lValue);
ClientHandleInfo * pi = new ClientHandleInfo(0);
strlcpy(pi->login, data->szBoard, sizeof(pi->login));
pi->account_id = (DWORD)data->lValue;
pi->player_id = data->dwPID;
pi->account_index = (data->cDir > 0);
strlcpy(board, data->szBoard, sizeof(board));
CDBManager::instance().ReturnQuery(szQuery, QID_HIGHSCORE_REGISTER, peer->GetHandle(), pi);
}
void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg)
{
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * pi = (ClientHandleInfo *) qi->pvData;
//DWORD dwHandle = pi->dwHandle;
char szBoard[21];
strlcpy(szBoard, pi->login, sizeof(szBoard));
const std::string escapedBoard = CDBManager::instance().EscapeStringCopy(szBoard, strnlen(szBoard, sizeof(szBoard)));
int value = (int)pi->account_id;
SQLResult * res = msg->Get();
if (res->uiNumRows == 0)
if (!LoadHighscoreValue(board, data->dwPID, currentValue, found))
{
// 새로운 하이스코어를 삽입
char buf[256];
snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), escapedBoard.c_str(), pi->player_id, value);
CDBManager::instance().AsyncQuery(buf);
sys_err("failed to load highscore for board %s pid %u", board, data->dwPID);
return;
}
else
if (found)
{
if (!res->pSQLResult)
{
delete pi;
if ((higherIsBetter && currentValue >= value) || (!higherIsBetter && currentValue <= value))
return;
}
MYSQL_ROW row = mysql_fetch_row(res->pSQLResult);
if (row && row[0])
{
int current_value = 0; str_to_number(current_value, row[0]);
if (pi->account_index && current_value >= value || !pi->account_index && current_value <= value)
{
value = current_value;
}
else
{
char buf[256];
snprintf(buf, sizeof(buf), "REPLACE INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), escapedBoard.c_str(), pi->player_id, value);
CDBManager::instance().AsyncQuery(buf);
}
}
else
{
char buf[256];
snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), escapedBoard.c_str(), pi->player_id, value);
CDBManager::instance().AsyncQuery(buf);
}
}
// TODO: 이곳에서 하이스코어가 업데이트 되었는지 체크하여 공지를 뿌려야한다.
delete pi;
if (!WriteHighscoreValue(board, data->dwPID, value, found))
sys_err("failed to write highscore for board %s pid %u", board, data->dwPID);
}
void CClientManager::InsertLogoutPlayer(DWORD pid)