Files
m2dev-server-src/src/db/ItemAwardManager.cpp
server bba87f939f
Some checks failed
build / Linux asan (push) Has been cancelled
build / Linux release (push) Has been cancelled
build / FreeBSD build (push) Has been cancelled
db: prepare item award manager queries
2026-04-14 14:48:05 +02:00

213 lines
6.1 KiB
C++

#include "stdafx.h"
#include "QID.h"
#include "DBManager.h"
#include "ItemAwardManager.h"
#include "Peer.h"
#include "libsql/Statement.h"
#include "ClientManager.h"
DWORD g_dwLastCachedItemAwardID = 0;
namespace
{
bool FallbackItemAwardLoadQuery()
{
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery),
"SELECT id,login,vnum,count,socket0,socket1,socket2,mall,why "
"FROM item_award WHERE taken_time IS NULL and id > %d",
g_dwLastCachedItemAwardID);
CDBManager::instance().ReturnQuery(szQuery, QID_ITEM_AWARD_LOAD, 0, NULL);
return true;
}
bool FallbackItemAwardTakenQuery(DWORD dwAwardID, DWORD dwItemID)
{
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery),
"UPDATE item_award SET taken_time=NOW(),item_id=%u WHERE id=%u AND taken_time IS NULL",
dwItemID, dwAwardID);
CDBManager::instance().ReturnQuery(szQuery, QID_ITEM_AWARD_TAKEN, 0, NULL);
return true;
}
void ProcessItemAwardRow(DWORD dwID, const char* login, DWORD dwVnum, DWORD dwCount,
DWORD dwSocket0, DWORD dwSocket1, DWORD dwSocket2, bool bMall, const char* why)
{
if (ItemAwardManager::instance().GetMapAward().find(dwID) != ItemAwardManager::instance().GetMapAward().end())
return;
TItemAward* kData = new TItemAward;
memset(kData, 0, sizeof(TItemAward));
kData->dwID = dwID;
trim_and_lower(login, kData->szLogin, sizeof(kData->szLogin));
kData->dwVnum = dwVnum;
kData->dwCount = dwCount;
kData->dwSocket0 = dwSocket0;
kData->dwSocket1 = dwSocket1;
kData->dwSocket2 = dwSocket2;
kData->bMall = bMall;
if (why && *why)
{
strlcpy(kData->szWhy, why, sizeof(kData->szWhy));
char* whyStr = kData->szWhy;
char cmdStr[100] = "";
strcpy(cmdStr, whyStr);
char command[20] = "";
strcpy(command, CClientManager::instance().GetCommand(cmdStr));
if (!(strcmp(command, "GIFT")))
{
TPacketItemAwardInfromer giftData;
strcpy(giftData.login, kData->szLogin);
strcpy(giftData.command, command);
giftData.vnum = kData->dwVnum;
CClientManager::instance().ForwardPacket(DG::ITEMAWARD_INFORMER, &giftData, sizeof(TPacketItemAwardInfromer));
}
}
ItemAwardManager::instance().GetMapAward().insert(std::make_pair(dwID, kData));
printf("ITEM_AWARD load id %u bMall %d \n", kData->dwID, kData->bMall);
sys_log(0, "ITEM_AWARD: load id %lu login %s vnum %lu count %u socket %lu", kData->dwID, kData->szLogin, kData->dwVnum, kData->dwCount, kData->dwSocket0);
std::set<TItemAward*>& kSet = ItemAwardManager::instance().GetMapkSetAwardByLogin()[kData->szLogin];
kSet.insert(kData);
if (dwID > g_dwLastCachedItemAwardID)
g_dwLastCachedItemAwardID = dwID;
}
}
ItemAwardManager::ItemAwardManager()
{
}
ItemAwardManager::~ItemAwardManager()
{
}
void ItemAwardManager::RequestLoad()
{
static const char* query =
"SELECT id, login, vnum, count, socket0, socket1, socket2, mall, COALESCE(why, '') "
"FROM item_award WHERE taken_time IS NULL AND id > ?";
CStmt stmt;
DWORD dwID = 0;
DWORD dwVnum = 0;
DWORD dwCount = 0;
DWORD dwSocket0 = 0;
DWORD dwSocket1 = 0;
DWORD dwSocket2 = 0;
char login[LOGIN_MAX_LEN + 1] = {};
char why[ITEM_AWARD_WHY_MAX_LEN + 1] = {};
DWORD dwMall = 0;
if (!stmt.Prepare(CDBManager::instance().GetDirectSQL(), query) ||
!stmt.BindParam(MYSQL_TYPE_LONG, &g_dwLastCachedItemAwardID) ||
!stmt.BindResult(MYSQL_TYPE_LONG, &dwID) ||
!stmt.BindResult(MYSQL_TYPE_STRING, login, sizeof(login)) ||
!stmt.BindResult(MYSQL_TYPE_LONG, &dwVnum) ||
!stmt.BindResult(MYSQL_TYPE_LONG, &dwCount) ||
!stmt.BindResult(MYSQL_TYPE_LONG, &dwSocket0) ||
!stmt.BindResult(MYSQL_TYPE_LONG, &dwSocket1) ||
!stmt.BindResult(MYSQL_TYPE_LONG, &dwSocket2) ||
!stmt.BindResult(MYSQL_TYPE_LONG, &dwMall) ||
!stmt.BindResult(MYSQL_TYPE_STRING, why, sizeof(why)) ||
!stmt.Execute())
{
sys_err("ITEM_AWARD: prepared load failed, falling back to legacy query path");
FallbackItemAwardLoadQuery();
return;
}
while (stmt.Fetch())
{
ProcessItemAwardRow(dwID, login, dwVnum, dwCount, dwSocket0, dwSocket1, dwSocket2, dwMall != 0, why);
memset(login, 0, sizeof(login));
memset(why, 0, sizeof(why));
}
}
void ItemAwardManager::Load(SQLMsg * pMsg)
{
MYSQL_RES * pRes = pMsg->Get()->pSQLResult;
for (uint i = 0; i < pMsg->Get()->uiNumRows; ++i)
{
MYSQL_ROW row = mysql_fetch_row(pRes);
int col = 0;
DWORD dwID = 0;
str_to_number(dwID, row[col++]);
const char* login = row[col++];
DWORD dwVnum = 0;
DWORD dwCount = 0;
DWORD dwSocket0 = 0;
DWORD dwSocket1 = 0;
DWORD dwSocket2 = 0;
DWORD dwMall = 0;
str_to_number(dwVnum, row[col++]);
str_to_number(dwCount, row[col++]);
str_to_number(dwSocket0, row[col++]);
str_to_number(dwSocket1, row[col++]);
str_to_number(dwSocket2, row[col++]);
str_to_number(dwMall, row[col++]);
ProcessItemAwardRow(dwID, login, dwVnum, dwCount, dwSocket0, dwSocket1, dwSocket2, dwMall != 0, row[col] ? row[col] : "");
}
}
std::set<TItemAward *> * ItemAwardManager::GetByLogin(const char * c_pszLogin)
{
itertype(m_map_kSetAwardByLogin) it = m_map_kSetAwardByLogin.find(c_pszLogin);
if (it == m_map_kSetAwardByLogin.end())
return NULL;
return &it->second;
}
void ItemAwardManager::Taken(DWORD dwAwardID, DWORD dwItemID)
{
itertype(m_map_award) it = m_map_award.find(dwAwardID);
if (it == m_map_award.end())
{
sys_log(0, "ITEM_AWARD: Taken ID not exist %lu", dwAwardID);
return;
}
TItemAward * k = it->second;
k->bTaken = true;
//
// Update taken_time in database to prevent not to give him again.
//
static const char* query =
"UPDATE item_award SET taken_time=NOW(), item_id=? WHERE id=? AND taken_time IS NULL";
CStmt stmt;
if (!stmt.Prepare(CDBManager::instance().GetDirectSQL(), query) ||
!stmt.BindParam(MYSQL_TYPE_LONG, &dwItemID) ||
!stmt.BindParam(MYSQL_TYPE_LONG, &dwAwardID) ||
!stmt.Execute())
{
sys_err("ITEM_AWARD: prepared taken update failed, falling back to legacy query path");
FallbackItemAwardTakenQuery(dwAwardID, dwItemID);
}
}
std::map<DWORD, TItemAward *>& ItemAwardManager::GetMapAward()
{
return m_map_award;
}
std::map<std::string, std::set<TItemAward *> >& ItemAwardManager::GetMapkSetAwardByLogin()
{
return m_map_kSetAwardByLogin;
}