#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& 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 * 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& ItemAwardManager::GetMapAward() { return m_map_award; } std::map >& ItemAwardManager::GetMapkSetAwardByLogin() { return m_map_kSetAwardByLogin; }