config: prepare locale bootstrap queries

This commit is contained in:
server
2026-04-13 22:03:41 +02:00
parent 4e9b721c44
commit 8721d9ba3e
2 changed files with 76 additions and 31 deletions

View File

@@ -21,6 +21,7 @@
#include "config.h"
#include "db.h"
#include "skill_power.h"
#include "libsql/Statement.h"
using std::string;
@@ -177,6 +178,19 @@ namespace
else
fprintf(stdout, "ADMIN_PAGE: enabled for %zu IP entries\n", g_stAdminPageIP.size());
}
bool PrepareAccountStmt(CStmt& stmt, const std::string& query)
{
CAsyncSQL2* sql = AccountDB::instance().GetDirectSQL();
if (!sql)
{
fprintf(stderr, "AccountDB direct SQL handle is not initialized\n");
return false;
}
return stmt.Prepare(sql, query.c_str());
}
}
BYTE g_bChannel = 0;
@@ -913,27 +927,41 @@ void config_init(const string& st_localeServiceName)
// 로케일 정보를 가져오자
// <경고> 쿼리문에 절대 조건문(WHERE) 달지 마세요. (다른 지역에서 문제가 생길수 있습니다)
{
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "SELECT mKey, mValue FROM locale");
CStmt stmt;
char localeKey[256];
char localeValue[4096];
const char* localeQuery = "SELECT mKey, mValue FROM locale";
auto pMsg = AccountDB::instance().DirectQuery(szQuery);
memset(localeKey, 0, sizeof(localeKey));
memset(localeValue, 0, sizeof(localeValue));
if (pMsg->Get()->uiNumRows == 0)
if (!PrepareAccountStmt(stmt, localeQuery)
|| !stmt.BindResult(MYSQL_TYPE_STRING, localeKey, sizeof(localeKey))
|| !stmt.BindResult(MYSQL_TYPE_STRING, localeValue, sizeof(localeValue))
|| !stmt.Execute()
|| stmt.iRows == 0)
{
fprintf(stderr, "COMMON_SQL: DirectQuery failed : %s\n", szQuery);
fprintf(stderr, "COMMON_SQL: DirectQuery failed : %s\n", localeQuery);
exit(1);
}
MYSQL_ROW row;
while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
for (int i = 0; i < stmt.iRows; ++i)
{
// 로케일 세팅
if (strcasecmp(row[0], "LOCALE") == 0)
memset(localeKey, 0, sizeof(localeKey));
memset(localeValue, 0, sizeof(localeValue));
if (!stmt.Fetch())
{
if (LocaleService_Init(row[1]) == false)
fprintf(stderr, "COMMON_SQL: DirectQuery failed : %s\n", localeQuery);
exit(1);
}
// 로케일 세팅
if (strcasecmp(localeKey, "LOCALE") == 0)
{
if (LocaleService_Init(localeValue) == false)
{
fprintf(stderr, "COMMON_SQL: invalid locale key %s\n", row[1]);
fprintf(stderr, "COMMON_SQL: invalid locale key %s\n", localeValue);
exit(1);
}
}
@@ -983,21 +1011,25 @@ void config_init(const string& st_localeServiceName)
// 스트링 비교의 문제로 인해서 AccountDB::instance().SetLocale(g_stLocale) 후부터 한다.
// 물론 국내는 별로 문제가 안된다(해외가 문제)
{
char szQuery[256];
snprintf(szQuery, sizeof(szQuery), "SELECT mValue FROM locale WHERE mKey='SKILL_POWER_BY_LEVEL'");
auto pMsg = AccountDB::instance().DirectQuery(szQuery);
CStmt stmt;
char localeKey[] = "SKILL_POWER_BY_LEVEL";
char skillPowerByLevel[4096];
const char* localeQuery = "SELECT mValue FROM locale WHERE mKey=?";
if (pMsg->Get()->uiNumRows == 0)
memset(skillPowerByLevel, 0, sizeof(skillPowerByLevel));
if (!PrepareAccountStmt(stmt, localeQuery)
|| !stmt.BindParam(MYSQL_TYPE_STRING, localeKey)
|| !stmt.BindResult(MYSQL_TYPE_STRING, skillPowerByLevel, sizeof(skillPowerByLevel))
|| !stmt.Execute()
|| stmt.iRows == 0
|| !stmt.Fetch())
{
fprintf(stderr, "[SKILL_PERCENT] Query failed: %s", szQuery);
fprintf(stderr, "[SKILL_PERCENT] Query failed: %s", localeQuery);
exit(1);
}
MYSQL_ROW row;
row = mysql_fetch_row(pMsg->Get()->pSQLResult);
const char * p = row[0];
const char * p = skillPowerByLevel;
int cnt = 0;
char num[128];
int aiBaseSkillPowerByLevelTable[SKILL_MAX_LEVEL+1];
@@ -1013,7 +1045,7 @@ void config_init(const string& st_localeServiceName)
{
if (cnt != (SKILL_MAX_LEVEL + 1))
{
fprintf(stderr, "[SKILL_PERCENT] locale table has not enough skill information! (count: %d query: %s)", cnt, szQuery);
fprintf(stderr, "[SKILL_PERCENT] locale table has not enough skill information! (count: %d query: %s)", cnt, localeQuery);
exit(1);
}
@@ -1025,19 +1057,32 @@ void config_init(const string& st_localeServiceName)
// 종족별 스킬 세팅
for (int job = 0; job < JOB_MAX_NUM * 2; ++job)
{
snprintf(szQuery, sizeof(szQuery), "SELECT mValue from locale where mKey='SKILL_POWER_BY_LEVEL_TYPE%d' ORDER BY CAST(mValue AS unsigned)", job);
auto pMsg = AccountDB::instance().DirectQuery(szQuery);
CStmt jobStmt;
char jobLocaleKey[64];
char skillPowerByJob[4096];
const char* jobQuery = "SELECT mValue FROM locale WHERE mKey=? ORDER BY CAST(mValue AS unsigned)";
// 세팅이 안되어있으면 기본테이블을 사용한다.
if (pMsg->Get()->uiNumRows == 0)
snprintf(jobLocaleKey, sizeof(jobLocaleKey), "SKILL_POWER_BY_LEVEL_TYPE%d", job);
memset(skillPowerByJob, 0, sizeof(skillPowerByJob));
if (!PrepareAccountStmt(jobStmt, jobQuery)
|| !jobStmt.BindParam(MYSQL_TYPE_STRING, jobLocaleKey)
|| !jobStmt.BindResult(MYSQL_TYPE_STRING, skillPowerByJob, sizeof(skillPowerByJob))
|| !jobStmt.Execute())
{
CTableBySkill::instance().SetSkillPowerByLevelFromType(job, aiBaseSkillPowerByLevelTable);
continue;
}
// 세팅이 안되어있으면 기본테이블을 사용한다.
if (jobStmt.iRows == 0 || !jobStmt.Fetch())
{
CTableBySkill::instance().SetSkillPowerByLevelFromType(job, aiBaseSkillPowerByLevelTable);
continue;
}
row = mysql_fetch_row(pMsg->Get()->pSQLResult);
cnt = 0;
p = row[0];
p = skillPowerByJob;
int aiSkillTable[SKILL_MAX_LEVEL + 1];
fprintf(stdout, "SKILL_POWER_BY_JOB %d %s\n", job, p);
@@ -1051,7 +1096,7 @@ void config_init(const string& st_localeServiceName)
{
if (cnt != (SKILL_MAX_LEVEL + 1))
{
fprintf(stderr, "[SKILL_PERCENT] locale table has not enough skill information! (count: %d query: %s)", cnt, szQuery);
fprintf(stderr, "[SKILL_PERCENT] locale table has not enough skill information! (count: %d query: %s)", cnt, jobQuery);
exit(1);
}
@@ -1300,4 +1345,3 @@ bool IsValidFileCRC(DWORD dwCRC)
{
return s_set_dwFileCRC.find(dwCRC) != s_set_dwFileCRC.end();
}

View File

@@ -166,6 +166,7 @@ class AccountDB : public singleton<AccountDB>
std::unique_ptr<SQLMsg> DirectQuery(const char* query);
void ReturnQuery(int iType, DWORD dwIdent, void * pvData, const char * c_pszFormat, ...);
void AsyncQuery(const char* query);
CAsyncSQL2* GetDirectSQL() { return &m_sql_direct; }
void SetLocale(const std::string & stLocale);