From dc76f5da879fd61c3b8d554b307309aaa9599672 Mon Sep 17 00:00:00 2001 From: server Date: Mon, 13 Apr 2026 21:37:32 +0200 Subject: [PATCH] game: prepare change empire queries --- src/game/char_change_empire.cpp | 319 +++++++++++++++++++++----------- 1 file changed, 208 insertions(+), 111 deletions(-) diff --git a/src/game/char_change_empire.cpp b/src/game/char_change_empire.cpp index d421dc8..36183ef 100644 --- a/src/game/char_change_empire.cpp +++ b/src/game/char_change_empire.cpp @@ -1,11 +1,181 @@  #include "stdafx.h" + +#include +#include #include "config.h" #include "char.h" #include "char_manager.h" #include "db.h" #include "guild_manager.h" #include "marriage.h" +#include "libsql/Statement.h" + +namespace +{ +struct PlayerIndexEmpireData +{ + uint32_t accountId = 0; + std::array playerIds = {}; +}; + +bool PrepareGameStmt(CStmt& stmt, const std::string& query) +{ + CAsyncSQL* sql = DBManager::instance().GetDirectSQL(); + + if (!sql) + { + sys_err("game direct SQL handle is not initialized"); + return false; + } + + return stmt.Prepare(sql, query.c_str()); +} + +bool LoadPlayerIndexEmpireData(uint32_t playerId, uint8_t empire, PlayerIndexEmpireData& data) +{ + CStmt stmt; + const std::string query = std::string("SELECT id, pid1, pid2, pid3, pid4 FROM player_index") + get_table_postfix() + + " WHERE (pid1=? OR pid2=? OR pid3=? OR pid4=?) AND empire=?"; + + if (!PrepareGameStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &playerId) + || !stmt.BindParam(MYSQL_TYPE_LONG, &playerId) + || !stmt.BindParam(MYSQL_TYPE_LONG, &playerId) + || !stmt.BindParam(MYSQL_TYPE_LONG, &playerId) + || !stmt.BindParam(MYSQL_TYPE_TINY, &empire)) + { + return false; + } + + if (!stmt.BindResult(MYSQL_TYPE_LONG, &data.accountId) + || !stmt.BindResult(MYSQL_TYPE_LONG, &data.playerIds[0]) + || !stmt.BindResult(MYSQL_TYPE_LONG, &data.playerIds[1]) + || !stmt.BindResult(MYSQL_TYPE_LONG, &data.playerIds[2]) + || !stmt.BindResult(MYSQL_TYPE_LONG, &data.playerIds[3])) + { + return false; + } + + if (!stmt.Execute() || stmt.iRows == 0 || !stmt.Fetch()) + return false; + + return true; +} + +bool LoadGuildIdByPlayerId(uint32_t playerId, uint32_t& guildId) +{ + CStmt stmt; + const std::string query = std::string("SELECT guild_id FROM guild_member") + get_table_postfix() + " WHERE pid=?"; + + guildId = 0; + + if (!PrepareGameStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &playerId) + || !stmt.BindResult(MYSQL_TYPE_LONG, &guildId)) + { + return false; + } + + if (!stmt.Execute()) + return false; + + if (stmt.iRows == 0) + return true; + + return stmt.Fetch(); +} + +bool UpdatePlayerIndexEmpire(uint32_t playerId, uint8_t currentEmpire, uint8_t newEmpire) +{ + CStmt stmt; + const std::string query = std::string("UPDATE player_index") + get_table_postfix() + + " SET empire=? WHERE (pid1=? OR pid2=? OR pid3=? OR pid4=?) AND empire=?"; + + if (!PrepareGameStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_TINY, &newEmpire) + || !stmt.BindParam(MYSQL_TYPE_LONG, &playerId) + || !stmt.BindParam(MYSQL_TYPE_LONG, &playerId) + || !stmt.BindParam(MYSQL_TYPE_LONG, &playerId) + || !stmt.BindParam(MYSQL_TYPE_LONG, &playerId) + || !stmt.BindParam(MYSQL_TYPE_TINY, ¤tEmpire)) + { + return false; + } + + return stmt.Execute(); +} + +bool LoadChangeEmpireCountForAccount(uint32_t accountId, uint32_t& count, bool& found) +{ + CStmt stmt; + const std::string query = "SELECT change_count FROM change_empire WHERE account_id=?"; + + count = 0; + found = false; + + if (!PrepareGameStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &accountId) + || !stmt.BindResult(MYSQL_TYPE_LONG, &count)) + { + return false; + } + + if (!stmt.Execute()) + return false; + + if (stmt.iRows == 0) + return true; + + if (!stmt.Fetch()) + return false; + + found = true; + return true; +} + +bool InsertChangeEmpireCount(uint32_t accountId, uint32_t count) +{ + CStmt stmt; + const std::string query = "INSERT INTO change_empire VALUES(?, ?, NOW())"; + + if (!PrepareGameStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &accountId) + || !stmt.BindParam(MYSQL_TYPE_LONG, &count)) + { + return false; + } + + return stmt.Execute(); +} + +bool UpdateChangeEmpireCount(uint32_t accountId, uint32_t count) +{ + CStmt stmt; + const std::string query = "UPDATE change_empire SET change_count=? WHERE account_id=?"; + + if (!PrepareGameStmt(stmt, query)) + return false; + + if (!stmt.BindParam(MYSQL_TYPE_LONG, &count) + || !stmt.BindParam(MYSQL_TYPE_LONG, &accountId)) + { + return false; + } + + return stmt.Execute(); +} +} /* Return Value @@ -21,31 +191,12 @@ int CHARACTER::ChangeEmpire(BYTE empire) if (GetEmpire() == empire) return 1; - char szQuery[1024+1]; - DWORD dwAID; - DWORD dwPID[4]; - memset(dwPID, 0, sizeof(dwPID)); + PlayerIndexEmpireData indexData; { // 1. 내 계정의 모든 pid를 얻어 온다 - snprintf(szQuery, sizeof(szQuery), - "SELECT id, pid1, pid2, pid3, pid4 FROM player_index%s WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u", - get_table_postfix(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire()); - - auto msg = DBManager::instance().DirectQuery(szQuery); - - if (msg->Get()->uiNumRows == 0) - { + if (!LoadPlayerIndexEmpireData(GetPlayerID(), GetEmpire(), indexData)) return 0; - } - - MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult); - - str_to_number(dwAID, row[0]); - str_to_number(dwPID[0], row[1]); - str_to_number(dwPID[1], row[2]); - str_to_number(dwPID[2], row[3]); - str_to_number(dwPID[3], row[4]); } const int loop = 4; @@ -53,36 +204,21 @@ int CHARACTER::ChangeEmpire(BYTE empire) { // 2. 각 캐릭터의 길드 정보를 얻어온다. // 한 캐릭터라도 길드에 가입 되어 있다면, 제국 이동을 할 수 없다. - DWORD dwGuildID[4]; - CGuild * pGuild[4]; - for (int i = 0; i < loop; ++i) { - snprintf(szQuery, sizeof(szQuery), "SELECT guild_id FROM guild_member%s WHERE pid=%u", get_table_postfix(), dwPID[i]); + uint32_t guildId = 0; + CGuild* guild = NULL; - auto pMsg = DBManager::instance().DirectQuery(szQuery); + if (indexData.playerIds[i] == 0) + continue; - if (pMsg != NULL) - { - if (pMsg->Get()->uiNumRows > 0) - { - MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult); + if (!LoadGuildIdByPlayerId(indexData.playerIds[i], guildId)) + return 0; - str_to_number(dwGuildID[i], row[0]); + guild = CGuildManager::instance().FindGuild(guildId); - pGuild[i] = CGuildManager::instance().FindGuild(dwGuildID[i]); - - if (pGuild[i] != NULL) - { - return 2; - } - } - else - { - dwGuildID[i] = 0; - pGuild[i] = NULL; - } - } + if (guild != NULL) + return 2; } } @@ -91,19 +227,17 @@ int CHARACTER::ChangeEmpire(BYTE empire) // 한 캐릭터라도 결혼 상태라면 제국 이동을 할 수 없다. for (int i = 0; i < loop; ++i) { - if (marriage::CManager::instance().IsEngagedOrMarried(dwPID[i]) == true) + if (indexData.playerIds[i] == 0) + continue; + + if (marriage::CManager::instance().IsEngagedOrMarried(indexData.playerIds[i]) == true) return 3; } } { // 4. db의 제국 정보를 업데이트 한다. - snprintf(szQuery, sizeof(szQuery), "UPDATE player_index%s SET empire=%u WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u", - get_table_postfix(), empire, GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire()); - - auto msg = DBManager::instance().DirectQuery(szQuery); - - if (msg->Get()->uiAffectedRows > 0) + if (UpdatePlayerIndexEmpire(GetPlayerID(), GetEmpire(), empire)) { // 5. 제국 변경 이력을 추가한다. SetChangeEmpireCount(); @@ -117,82 +251,45 @@ int CHARACTER::ChangeEmpire(BYTE empire) int CHARACTER::GetChangeEmpireCount() const { - char szQuery[1024+1]; - DWORD dwAID = GetAID(); + uint32_t count = 0; + bool found = false; + const uint32_t accountId = GetAID(); - if (dwAID == 0) + if (accountId == 0) return 0; - snprintf(szQuery, sizeof(szQuery), "SELECT change_count FROM change_empire WHERE account_id = %u", dwAID); + if (!LoadChangeEmpireCountForAccount(accountId, count, found) || !found) + return 0; - auto pMsg = DBManager::instance().DirectQuery(szQuery); - - if (pMsg != NULL) - { - if (pMsg->Get()->uiNumRows == 0) - { - return 0; - } - - MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult); - - DWORD count = 0; - str_to_number(count, row[0]); - - return count; - } - - return 0; + return count; } void CHARACTER::SetChangeEmpireCount() { - char szQuery[1024+1]; + const uint32_t accountId = GetAID(); + uint32_t count = 0; + bool found = false; - DWORD dwAID = GetAID(); + if (accountId == 0) + return; - if (dwAID == 0) return; + if (!LoadChangeEmpireCountForAccount(accountId, count, found)) + return; - int count = GetChangeEmpireCount(); + ++count; - if (count == 0) - { - count++; - snprintf(szQuery, sizeof(szQuery), "INSERT INTO change_empire VALUES(%u, %d, NOW())", dwAID, count); - } + if (!found) + InsertChangeEmpireCount(accountId, count); else - { - count++; - snprintf(szQuery, sizeof(szQuery), "UPDATE change_empire SET change_count=%d WHERE account_id=%u", count, dwAID); - } - - DBManager::instance().DirectQuery(szQuery); + UpdateChangeEmpireCount(accountId, count); } DWORD CHARACTER::GetAID() const { - char szQuery[1024+1]; - DWORD dwAID = 0; + PlayerIndexEmpireData indexData; - snprintf(szQuery, sizeof(szQuery), "SELECT id FROM player_index%s WHERE pid1=%u OR pid2=%u OR pid3=%u OR pid4=%u AND empire=%u", - get_table_postfix(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire()); - - auto pMsg = DBManager::instance().DirectQuery(szQuery); - - if (pMsg) - { - if (pMsg->Get()->uiNumRows == 0) - return 0; - - MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult); - - str_to_number(dwAID, row[0]); - - return dwAID; - } - else - { + if (!LoadPlayerIndexEmpireData(GetPlayerID(), GetEmpire(), indexData)) return 0; - } -} + return indexData.accountId; +}