game: prepare change empire queries

This commit is contained in:
server
2026-04-13 21:37:32 +02:00
parent 2bbd624c9a
commit dc76f5da87

View File

@@ -1,11 +1,181 @@
#include "stdafx.h" #include "stdafx.h"
#include <array>
#include <string>
#include "config.h" #include "config.h"
#include "char.h" #include "char.h"
#include "char_manager.h" #include "char_manager.h"
#include "db.h" #include "db.h"
#include "guild_manager.h" #include "guild_manager.h"
#include "marriage.h" #include "marriage.h"
#include "libsql/Statement.h"
namespace
{
struct PlayerIndexEmpireData
{
uint32_t accountId = 0;
std::array<uint32_t, 4> 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, &currentEmpire))
{
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 Return Value
@@ -21,31 +191,12 @@ int CHARACTER::ChangeEmpire(BYTE empire)
if (GetEmpire() == empire) if (GetEmpire() == empire)
return 1; return 1;
char szQuery[1024+1]; PlayerIndexEmpireData indexData;
DWORD dwAID;
DWORD dwPID[4];
memset(dwPID, 0, sizeof(dwPID));
{ {
// 1. 내 계정의 모든 pid를 얻어 온다 // 1. 내 계정의 모든 pid를 얻어 온다
snprintf(szQuery, sizeof(szQuery), if (!LoadPlayerIndexEmpireData(GetPlayerID(), GetEmpire(), indexData))
"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)
{
return 0; 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; const int loop = 4;
@@ -53,36 +204,21 @@ int CHARACTER::ChangeEmpire(BYTE empire)
{ {
// 2. 각 캐릭터의 길드 정보를 얻어온다. // 2. 각 캐릭터의 길드 정보를 얻어온다.
// 한 캐릭터라도 길드에 가입 되어 있다면, 제국 이동을 할 수 없다. // 한 캐릭터라도 길드에 가입 되어 있다면, 제국 이동을 할 수 없다.
DWORD dwGuildID[4];
CGuild * pGuild[4];
for (int i = 0; i < loop; ++i) 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 (!LoadGuildIdByPlayerId(indexData.playerIds[i], guildId))
{ return 0;
if (pMsg->Get()->uiNumRows > 0)
{
MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
str_to_number(dwGuildID[i], row[0]); guild = CGuildManager::instance().FindGuild(guildId);
pGuild[i] = CGuildManager::instance().FindGuild(dwGuildID[i]); if (guild != NULL)
return 2;
if (pGuild[i] != NULL)
{
return 2;
}
}
else
{
dwGuildID[i] = 0;
pGuild[i] = NULL;
}
}
} }
} }
@@ -91,19 +227,17 @@ int CHARACTER::ChangeEmpire(BYTE empire)
// 한 캐릭터라도 결혼 상태라면 제국 이동을 할 수 없다. // 한 캐릭터라도 결혼 상태라면 제국 이동을 할 수 없다.
for (int i = 0; i < loop; ++i) 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; return 3;
} }
} }
{ {
// 4. db의 제국 정보를 업데이트 한다. // 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", if (UpdatePlayerIndexEmpire(GetPlayerID(), GetEmpire(), empire))
get_table_postfix(), empire, GetPlayerID(), GetPlayerID(), GetPlayerID(), GetPlayerID(), GetEmpire());
auto msg = DBManager::instance().DirectQuery(szQuery);
if (msg->Get()->uiAffectedRows > 0)
{ {
// 5. 제국 변경 이력을 추가한다. // 5. 제국 변경 이력을 추가한다.
SetChangeEmpireCount(); SetChangeEmpireCount();
@@ -117,82 +251,45 @@ int CHARACTER::ChangeEmpire(BYTE empire)
int CHARACTER::GetChangeEmpireCount() const int CHARACTER::GetChangeEmpireCount() const
{ {
char szQuery[1024+1]; uint32_t count = 0;
DWORD dwAID = GetAID(); bool found = false;
const uint32_t accountId = GetAID();
if (dwAID == 0) if (accountId == 0)
return 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); return count;
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;
} }
void CHARACTER::SetChangeEmpireCount() 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) if (!found)
{ InsertChangeEmpireCount(accountId, count);
count++;
snprintf(szQuery, sizeof(szQuery), "INSERT INTO change_empire VALUES(%u, %d, NOW())", dwAID, count);
}
else else
{ UpdateChangeEmpireCount(accountId, count);
count++;
snprintf(szQuery, sizeof(szQuery), "UPDATE change_empire SET change_count=%d WHERE account_id=%u", count, dwAID);
}
DBManager::instance().DirectQuery(szQuery);
} }
DWORD CHARACTER::GetAID() const DWORD CHARACTER::GetAID() const
{ {
char szQuery[1024+1]; PlayerIndexEmpireData indexData;
DWORD dwAID = 0;
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", if (!LoadPlayerIndexEmpireData(GetPlayerID(), GetEmpire(), indexData))
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
{
return 0; return 0;
}
}
return indexData.accountId;
}