game: prepare name lookup queries

This commit is contained in:
server
2026-04-13 21:42:22 +02:00
parent dc76f5da87
commit cc8fa1e78a
2 changed files with 134 additions and 30 deletions

View File

@@ -15,9 +15,55 @@
#include "locale_service.h"
#include "guild_manager.h"
#include "MarkManager.h"
#include "libsql/Statement.h"
#include <string>
namespace
{
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 GuildNameExists(const char* guildName, bool& exists)
{
CStmt stmt;
const std::string query = std::string("SELECT COUNT(*) FROM guild") + get_table_postfix() + " WHERE name=?";
uint32_t count = 0;
exists = false;
if (!PrepareGameStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_STRING, const_cast<char*>(guildName))
|| !stmt.BindResult(MYSQL_TYPE_LONG, &count))
{
return false;
}
if (!stmt.Execute())
return false;
if (stmt.iRows == 0)
return true;
if (!stmt.Fetch())
return false;
exists = count != 0;
return true;
}
struct FGuildNameSender
{
@@ -81,25 +127,20 @@ DWORD CGuildManager::CreateGuild(TGuildCreateParameter& gcp)
return 0;
}
auto pmsg = DBManager::instance().DirectQuery("SELECT COUNT(*) FROM guild%s WHERE name = '%s'",
get_table_postfix(), gcp.name);
bool guildNameExists = false;
if (pmsg->Get()->uiNumRows > 0)
{
MYSQL_ROW row = mysql_fetch_row(pmsg->Get()->pSQLResult);
if (!(row[0] && row[0][0] == '0'))
{
gcp.master->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<길드> 이미 같은 이름의 길드가 있습니다."));
return 0;
}
}
else
if (!GuildNameExists(gcp.name, guildNameExists))
{
gcp.master->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<길드> 길드를 생성할 수 없습니다."));
return 0;
}
if (guildNameExists)
{
gcp.master->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("<길드> 이미 같은 이름의 길드가 있습니다."));
return 0;
}
// new CGuild(gcp) queries guild tables and tell dbcache to notice other game servers.
// other game server calls CGuildManager::LoadGuild to load guild.
CGuild * pg = M2_NEW CGuild(gcp);
@@ -956,4 +997,3 @@ void CGuildManager::ChangeMaster(DWORD dwGID)
"SELECT 1");
}

View File

@@ -19,9 +19,11 @@
#include "desc_client.h"
#include "messenger_manager.h"
#include "log.h"
#include "db.h"
#include "utils.h"
#include "unique_item.h"
#include "mob_manager.h"
#include "libsql/Statement.h"
#include <cctype>
#undef sys_err
@@ -31,6 +33,69 @@ extern int g_nPortalLimitTime;
extern LPCLIENT_DESC db_clientdesc;
const int ITEM_BROKEN_METIN_VNUM = 28960;
namespace
{
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 CharacterNameExists(const char* name, bool& exists)
{
CStmt stmt;
const std::string query = std::string("SELECT COUNT(*) FROM player") + get_table_postfix() + " WHERE name=?";
uint32_t count = 0;
exists = false;
if (!PrepareGameStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_STRING, const_cast<char*>(name))
|| !stmt.BindResult(MYSQL_TYPE_LONG, &count))
{
return false;
}
if (!stmt.Execute())
return false;
if (stmt.iRows == 0)
return true;
if (!stmt.Fetch())
return false;
exists = count != 0;
return true;
}
bool UpdateCharacterName(uint32_t playerId, const char* name)
{
CStmt stmt;
const std::string query = std::string("UPDATE player") + get_table_postfix() + " SET name=? WHERE id=?";
if (!PrepareGameStmt(stmt, query))
return false;
if (!stmt.BindParam(MYSQL_TYPE_STRING, const_cast<char*>(name))
|| !stmt.BindParam(MYSQL_TYPE_LONG, &playerId))
{
return false;
}
return stmt.Execute();
}
}
namespace quest
{
//
@@ -2114,23 +2179,19 @@ teleport_area:
return 1;
}
char szQuery[1024];
snprintf(szQuery, sizeof(szQuery), "SELECT COUNT(*) FROM player%s WHERE name='%s'", get_table_postfix(), szName);
auto pmsg = DBManager::instance().DirectQuery(szQuery);
bool characterNameExists = false;
if ( pmsg->Get()->uiNumRows > 0 )
if (!CharacterNameExists(szName, characterNameExists))
{
MYSQL_ROW row = mysql_fetch_row(pmsg->Get()->pSQLResult);
lua_pushnumber(L, 0);
return 1;
}
int count = 0;
str_to_number(count, row[0]);
// 이미 해당 이름을 가진 캐릭터가 있음
if ( count != 0 )
{
lua_pushnumber(L, 3);
return 1;
}
// 이미 해당 이름을 가진 캐릭터가 있음
if (characterNameExists)
{
lua_pushnumber(L, 3);
return 1;
}
DWORD pid = ch->GetPlayerID();
@@ -2144,8 +2205,11 @@ teleport_area:
/* change_name_log */
LogManager::instance().ChangeNameLog(pid, ch->GetName(), szName, ch->GetDesc()->GetHostName());
snprintf(szQuery, sizeof(szQuery), "UPDATE player%s SET name='%s' WHERE id=%u", get_table_postfix(), szName, pid);
DBManager::instance().DirectQuery(szQuery);
if (!UpdateCharacterName(pid, szName))
{
lua_pushnumber(L, 0);
return 1;
}
ch->SetNewName(szName);
lua_pushnumber(L, 4);