#include "stdafx.h" #include "ClientManager.h" #include "Main.h" #include "QID.h" #include "ItemAwardManager.h" #include "HB.h" #include "Cache.h" extern bool g_bHotBackup; extern std::string g_stLocale; extern int g_test_server; extern int g_log; // // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // !!!!!!!!!!! IMPORTANT !!!!!!!!!!!! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // // Check all SELECT syntax on item table before change this function!!! // bool CreateItemTableFromRes(MYSQL_RES * res, std::vector * pVec, DWORD dwPID) { if (!res) { pVec->clear(); return true; } int rows; if ((rows = mysql_num_rows(res)) <= 0) // µ¥ÀÌÅÍ ¾øÀ½ { pVec->clear(); return true; } pVec->resize(rows); for (int i = 0; i < rows; ++i) { MYSQL_ROW row = mysql_fetch_row(res); TPlayerItem & item = pVec->at(i); int cur = 0; // Check all SELECT syntax on item table before change this function!!! // Check all SELECT syntax on item table before change this function!!! // Check all SELECT syntax on item table before change this function!!! str_to_number(item.id, row[cur++]); str_to_number(item.window, row[cur++]); str_to_number(item.pos, row[cur++]); str_to_number(item.count, row[cur++]); str_to_number(item.vnum, row[cur++]); str_to_number(item.alSockets[0], row[cur++]); str_to_number(item.alSockets[1], row[cur++]); str_to_number(item.alSockets[2], row[cur++]); for (int j = 0; j < ITEM_ATTRIBUTE_MAX_NUM; j++) { str_to_number(item.aAttr[j].bType, row[cur++]); str_to_number(item.aAttr[j].sValue, row[cur++]); } item.owner = dwPID; } return true; } size_t CreatePlayerSaveQuery(char * pszQuery, size_t querySize, TPlayerTable * pkTab) { size_t queryLen; queryLen = snprintf(pszQuery, querySize, "UPDATE player%s SET " "job = %d, " "voice = %d, " "dir = %d, " "x = %d, " "y = %d, " "z = %d, " "map_index = %d, " "exit_x = %ld, " "exit_y = %ld, " "exit_map_index = %ld, " "hp = %d, " "mp = %d, " "stamina = %d, " "random_hp = %d, " "random_sp = %d, " "playtime = %d, " "level = %d, " "level_step = %d, " "st = %d, " "ht = %d, " "dx = %d, " "iq = %d, " "gold = %d, " "exp = %u, " "stat_point = %d, " "skill_point = %d, " "sub_skill_point = %d, " "stat_reset_count = %d, " "ip = '%s', " "part_main = %d, " "part_hair = %d, " "last_play = NOW(), " "skill_group = %d, " "alignment = %ld, " "horse_level = %d, " "horse_riding = %d, " "horse_hp = %d, " "horse_hp_droptime = %u, " "horse_stamina = %d, " "horse_skill_point = %d, " , GetTablePostfix(), pkTab->job, pkTab->voice, pkTab->dir, pkTab->x, pkTab->y, pkTab->z, pkTab->lMapIndex, pkTab->lExitX, pkTab->lExitY, pkTab->lExitMapIndex, pkTab->hp, pkTab->sp, pkTab->stamina, pkTab->sRandomHP, pkTab->sRandomSP, pkTab->playtime, pkTab->level, pkTab->level_step, pkTab->st, pkTab->ht, pkTab->dx, pkTab->iq, pkTab->gold, pkTab->exp, pkTab->stat_point, pkTab->skill_point, pkTab->sub_skill_point, pkTab->stat_reset_count, pkTab->ip, pkTab->parts[PART_MAIN], pkTab->parts[PART_HAIR], pkTab->skill_group, pkTab->lAlignment, pkTab->horse.bLevel, pkTab->horse.bRiding, pkTab->horse.sHealth, pkTab->horse.dwHorseHealthDropTime, pkTab->horse.sStamina, pkTab->horse_skill_point); // Binary ·Î ¹Ù²Ù±â À§ÇÑ Àӽà °ø°£ char text[8192 + 1]; CDBManager::instance().EscapeString(text, pkTab->skills, sizeof(pkTab->skills)); queryLen += snprintf(pszQuery + queryLen, querySize - queryLen, "skill_level = '%s', ", text); CDBManager::instance().EscapeString(text, pkTab->quickslot, sizeof(pkTab->quickslot)); queryLen += snprintf(pszQuery + queryLen, querySize - queryLen, "quickslot = '%s' ", text); queryLen += snprintf(pszQuery + queryLen, querySize - queryLen, " WHERE id=%d", pkTab->id); return queryLen; } CPlayerTableCache * CClientManager::GetPlayerCache(DWORD id) { TPlayerTableCacheMap::iterator it = m_map_playerCache.find(id); if (it == m_map_playerCache.end()) return NULL; TPlayerTable* pTable = it->second->Get(false); pTable->logoff_interval = GetCurrentTime() - it->second->GetLastUpdateTime(); return it->second; } void CClientManager::PutPlayerCache(TPlayerTable * pNew) { CPlayerTableCache * c; c = GetPlayerCache(pNew->id); if (!c) { c = new CPlayerTableCache; m_map_playerCache.insert(TPlayerTableCacheMap::value_type(pNew->id, c)); } if (g_bHotBackup) PlayerHB::instance().Put(pNew->id); c->Put(pNew); } /* * PLAYER LOAD */ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoadPacket * packet) { CPlayerTableCache * c; TPlayerTable * pTab; // // ÇÑ °èÁ¤¿¡ ¼ÓÇÑ ¸ðµç ij¸¯Å͵é ij½¬Ã³¸® // CLoginData * pLoginData = GetLoginDataByAID(packet->account_id); if (pLoginData) { for (int n = 0; n < PLAYER_PER_ACCOUNT; ++n) if (pLoginData->GetAccountRef().players[n].dwID != 0) DeleteLogoutPlayer(pLoginData->GetAccountRef().players[n].dwID); } //---------------------------------------------------------------- // 1. À¯ÀúÁ¤º¸°¡ DBCache ¿¡ Á¸Àç : DBCache¿¡¼­ // 2. À¯ÀúÁ¤º¸°¡ DBCache ¿¡ ¾øÀ½ : DB¿¡¼­ // --------------------------------------------------------------- //---------------------------------- // 1. À¯ÀúÁ¤º¸°¡ DBCache ¿¡ Á¸Àç : DBCache¿¡¼­ //---------------------------------- if ((c = GetPlayerCache(packet->player_id))) { CLoginData * pkLD = GetLoginDataByAID(packet->account_id); if (!pkLD || pkLD->IsPlay()) { sys_log(0, "PLAYER_LOAD_ERROR: LoginData %p IsPlay %d", pkLD, pkLD ? pkLD->IsPlay() : 0); peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_FAILED, dwHandle, 0); return; } pTab = c->Get(); pkLD->SetPlay(true); SendLoginToBilling(pkLD, true); memcpy(pTab->aiPremiumTimes, pkLD->GetPremiumPtr(), sizeof(pTab->aiPremiumTimes)); peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_SUCCESS, dwHandle, sizeof(TPlayerTable)); peer->Encode(pTab, sizeof(TPlayerTable)); if (packet->player_id != pkLD->GetLastPlayerID()) { TPacketNeedLoginLogInfo logInfo; logInfo.dwPlayerID = packet->player_id; pkLD->SetLastPlayerID( packet->player_id ); peer->EncodeHeader( HEADER_DG_NEED_LOGIN_LOG, dwHandle, sizeof(TPacketNeedLoginLogInfo) ); peer->Encode( &logInfo, sizeof(TPacketNeedLoginLogInfo) ); } char szQuery[1024] = { 0, }; TItemCacheSet * pSet = GetItemCacheSet(pTab->id); sys_log(0, "[PLAYER_LOAD] ID %s pid %d gold %d ", pTab->name, pTab->id, pTab->gold); //-------------------------------------------- // ¾ÆÀÌÅÛ & AFFECT & QUEST ·Îµù : //-------------------------------------------- // 1) ¾ÆÀÌÅÛÀÌ DBCache ¿¡ Á¸Àç : DBCache ¿¡¼­ °¡Á®¿È // 2) ¾ÆÀÌÅÛÀÌ DBCache ¿¡ ¾øÀ½ : DB ¿¡¼­ °¡Á®¿È ///////////////////////////////////////////// // 1) ¾ÆÀÌÅÛÀÌ DBCache ¿¡ Á¸Àç : DBCache ¿¡¼­ °¡Á®¿È ///////////////////////////////////////////// if (pSet) { static std::vector s_items; s_items.resize(pSet->size()); DWORD dwCount = 0; TItemCacheSet::iterator it = pSet->begin(); while (it != pSet->end()) { CItemCache * c = *it++; TPlayerItem * p = c->Get(); if (p->vnum) // vnumÀÌ ¾øÀ¸¸é »èÁ¦µÈ ¾ÆÀÌÅÛÀÌ´Ù. memcpy(&s_items[dwCount++], p, sizeof(TPlayerItem)); } if (g_test_server) sys_log(0, "ITEM_CACHE: HIT! %s count: %u", pTab->name, dwCount); peer->EncodeHeader(HEADER_DG_ITEM_LOAD, dwHandle, sizeof(DWORD) + sizeof(TPlayerItem) * dwCount); peer->EncodeDWORD(dwCount); if (dwCount) peer->Encode(&s_items[0], sizeof(TPlayerItem) * dwCount); // Quest snprintf(szQuery, sizeof(szQuery), "SELECT dwPID,szName,szState,lValue FROM quest%s WHERE dwPID=%d AND lValue<>0", GetTablePostfix(), pTab->id); CDBManager::instance().ReturnQuery(szQuery, QID_QUEST, peer->GetHandle(), new ClientHandleInfo(dwHandle,0,packet->account_id)); // Affect snprintf(szQuery, sizeof(szQuery), "SELECT dwPID,bType,bApplyOn,lApplyValue,dwFlag,lDuration,lSPCost FROM affect%s WHERE dwPID=%d", GetTablePostfix(), pTab->id); CDBManager::instance().ReturnQuery(szQuery, QID_AFFECT, peer->GetHandle(), new ClientHandleInfo(dwHandle)); } ///////////////////////////////////////////// // 2) ¾ÆÀÌÅÛÀÌ DBCache ¿¡ ¾øÀ½ : DB ¿¡¼­ °¡Á®¿È ///////////////////////////////////////////// else { snprintf(szQuery, sizeof(szQuery), "SELECT id,window+0,pos,count,vnum,socket0,socket1,socket2,attrtype0,attrvalue0,attrtype1,attrvalue1,attrtype2,attrvalue2,attrtype3,attrvalue3,attrtype4,attrvalue4,attrtype5,attrvalue5,attrtype6,attrvalue6 " "FROM item%s WHERE owner_id=%d AND (window < %d or window = %d)", GetTablePostfix(), pTab->id, SAFEBOX, DRAGON_SOUL_INVENTORY); CDBManager::instance().ReturnQuery(szQuery, QID_ITEM, peer->GetHandle(), new ClientHandleInfo(dwHandle, pTab->id)); snprintf(szQuery, sizeof(szQuery), "SELECT dwPID, szName, szState, lValue FROM quest%s WHERE dwPID=%d", GetTablePostfix(), pTab->id); CDBManager::instance().ReturnQuery(szQuery, QID_QUEST, peer->GetHandle(), new ClientHandleInfo(dwHandle, pTab->id)); snprintf(szQuery, sizeof(szQuery), "SELECT dwPID, bType, bApplyOn, lApplyValue, dwFlag, lDuration, lSPCost FROM affect%s WHERE dwPID=%d", GetTablePostfix(), pTab->id); CDBManager::instance().ReturnQuery(szQuery, QID_AFFECT, peer->GetHandle(), new ClientHandleInfo(dwHandle, pTab->id)); } //ljw //return; } //---------------------------------- // 2. À¯ÀúÁ¤º¸°¡ DBCache ¿¡ ¾øÀ½ : DB¿¡¼­ //---------------------------------- else { sys_log(0, "[PLAYER_LOAD] Load from PlayerDB pid[%d]", packet->player_id); char queryStr[QUERY_MAX_LEN]; //-------------------------------------------------------------- // ij¸¯ÅÍ Á¤º¸ ¾ò¾î¿À±â : ¹«Á¶°Ç DB¿¡¼­ //-------------------------------------------------------------- snprintf(queryStr, sizeof(queryStr), "SELECT " "id,name,job,voice,dir,x,y,z,map_index,exit_x,exit_y,exit_map_index,hp,mp,stamina,random_hp,random_sp,playtime," "gold,level,level_step,st,ht,dx,iq,exp," "stat_point,skill_point,sub_skill_point,stat_reset_count,part_base,part_hair," "skill_level,quickslot,skill_group,alignment,mobile,horse_level,horse_riding,horse_hp,horse_hp_droptime,horse_stamina," "UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(last_play),horse_skill_point FROM player%s WHERE id=%d", GetTablePostfix(), packet->player_id); ClientHandleInfo * pkInfo = new ClientHandleInfo(dwHandle, packet->player_id); pkInfo->account_id = packet->account_id; CDBManager::instance().ReturnQuery(queryStr, QID_PLAYER, peer->GetHandle(), pkInfo); //-------------------------------------------------------------- // ¾ÆÀÌÅÛ °¡Á®¿À±â //-------------------------------------------------------------- snprintf(queryStr, sizeof(queryStr), "SELECT id,window+0,pos,count,vnum,socket0,socket1,socket2,attrtype0,attrvalue0,attrtype1,attrvalue1,attrtype2,attrvalue2,attrtype3,attrvalue3,attrtype4,attrvalue4,attrtype5,attrvalue5,attrtype6,attrvalue6 " "FROM item%s WHERE owner_id=%d AND (window < %d or window = %d)", GetTablePostfix(), packet->player_id, SAFEBOX, DRAGON_SOUL_INVENTORY); CDBManager::instance().ReturnQuery(queryStr, QID_ITEM, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id)); //-------------------------------------------------------------- // QUEST °¡Á®¿À±â //-------------------------------------------------------------- snprintf(queryStr, sizeof(queryStr), "SELECT dwPID,szName,szState,lValue FROM quest%s WHERE dwPID=%d", GetTablePostfix(), packet->player_id); CDBManager::instance().ReturnQuery(queryStr, QID_QUEST, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id,packet->account_id)); //µ¶ÀÏ ¼±¹° ±â´É¿¡¼­ item_awardÅ×ÀÌºí¿¡¼­ login Á¤º¸¸¦ ¾ò±âÀ§ÇØ account idµµ ³Ñ°ÜÁØ´Ù //-------------------------------------------------------------- // AFFECT °¡Á®¿À±â //-------------------------------------------------------------- snprintf(queryStr, sizeof(queryStr), "SELECT dwPID,bType,bApplyOn,lApplyValue,dwFlag,lDuration,lSPCost FROM affect%s WHERE dwPID=%d", GetTablePostfix(), packet->player_id); CDBManager::instance().ReturnQuery(queryStr, QID_AFFECT, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id)); } } void CClientManager::ItemAward(CPeer * peer,char* login) { char login_t[LOGIN_MAX_LEN + 1] = ""; strncpy(login_t,login,LOGIN_MAX_LEN + 1); std::set * pSet = ItemAwardManager::instance().GetByLogin(login_t); if(pSet == NULL) return; typeof(pSet->begin()) it = pSet->begin(); //taken_timeÀÌ NULLÀΰ͵é Àоî¿È while(it != pSet->end() ) { TItemAward * pItemAward = *(it++); char* whyStr = pItemAward->szWhy; //why ÄÝ·ë Àбâ char cmdStr[100] = ""; //whyÄÝ·ë¿¡¼­ ÀÐÀº °ªÀ» Àӽà ¹®ÀÚ¿­¿¡ º¹»çÇØµÒ strcpy(cmdStr,whyStr); //¸í·É¾î ¾ò´Â °úÁ¤¿¡¼­ ÅäÅ«¾²¸é ¿øº»µµ ÅäÅ«È­ µÇ±â ¶§¹® char command[20] = ""; strcpy(command,GetCommand(cmdStr)); // command ¾ò±â if( !(strcmp(command,"GIFT") )) // command °¡ GIFTÀ̸é { TPacketItemAwardInfromer giftData; strcpy(giftData.login, pItemAward->szLogin); //·Î±×ÀÎ ¾ÆÀ̵𠺹»ç strcpy(giftData.command, command); //¸í·É¾î º¹»ç giftData.vnum = pItemAward->dwVnum; //¾ÆÀÌÅÛ vnumµµ º¹»ç ForwardPacket(HEADER_DG_ITEMAWARD_INFORMER,&giftData,sizeof(TPacketItemAwardInfromer)); } } } char* CClientManager::GetCommand(char* str) { char command[20] = ""; char* tok; if( str[0] == '[' ) { tok = strtok(str,"]"); strcat(command,&tok[1]); } return command; } bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab) { if (mysql_num_rows(res) == 0) // µ¥ÀÌÅÍ ¾øÀ½ return false; memset(pkTab, 0, sizeof(TPlayerTable)); MYSQL_ROW row = mysql_fetch_row(res); int col = 0; // "id,name,job,voice,dir,x,y,z,map_index,exit_x,exit_y,exit_map_index,hp,mp,stamina,random_hp,random_sp,playtime," // "gold,level,level_step,st,ht,dx,iq,exp," // "stat_point,skill_point,sub_skill_point,stat_reset_count,part_base,part_hair," // "skill_level,quickslot,skill_group,alignment,mobile,horse_level,horse_riding,horse_hp,horse_stamina FROM player%s WHERE id=%d", str_to_number(pkTab->id, row[col++]); strncpy(pkTab->name, row[col++], sizeof(pkTab->name)); str_to_number(pkTab->job, row[col++]); str_to_number(pkTab->voice, row[col++]); str_to_number(pkTab->dir, row[col++]); str_to_number(pkTab->x, row[col++]); str_to_number(pkTab->y, row[col++]); str_to_number(pkTab->z, row[col++]); str_to_number(pkTab->lMapIndex, row[col++]); str_to_number(pkTab->lExitX, row[col++]); str_to_number(pkTab->lExitY, row[col++]); str_to_number(pkTab->lExitMapIndex, row[col++]); str_to_number(pkTab->hp, row[col++]); str_to_number(pkTab->sp, row[col++]); str_to_number(pkTab->stamina, row[col++]); str_to_number(pkTab->sRandomHP, row[col++]); str_to_number(pkTab->sRandomSP, row[col++]); str_to_number(pkTab->playtime, row[col++]); str_to_number(pkTab->gold, row[col++]); str_to_number(pkTab->level, row[col++]); str_to_number(pkTab->level_step, row[col++]); str_to_number(pkTab->st, row[col++]); str_to_number(pkTab->ht, row[col++]); str_to_number(pkTab->dx, row[col++]); str_to_number(pkTab->iq, row[col++]); str_to_number(pkTab->exp, row[col++]); str_to_number(pkTab->stat_point, row[col++]); str_to_number(pkTab->skill_point, row[col++]); str_to_number(pkTab->sub_skill_point, row[col++]); str_to_number(pkTab->stat_reset_count, row[col++]); str_to_number(pkTab->part_base, row[col++]); str_to_number(pkTab->parts[PART_HAIR], row[col++]); if (row[col]) memcpy(pkTab->skills, row[col], sizeof(pkTab->skills)); else memset(&pkTab->skills, 0, sizeof(pkTab->skills)); col++; if (row[col]) memcpy(pkTab->quickslot, row[col], sizeof(pkTab->quickslot)); else memset(pkTab->quickslot, 0, sizeof(pkTab->quickslot)); col++; str_to_number(pkTab->skill_group, row[col++]); str_to_number(pkTab->lAlignment, row[col++]); if (row[col]) { strncpy(pkTab->szMobile, row[col], sizeof(pkTab->szMobile)); } col++; str_to_number(pkTab->horse.bLevel, row[col++]); str_to_number(pkTab->horse.bRiding, row[col++]); str_to_number(pkTab->horse.sHealth, row[col++]); str_to_number(pkTab->horse.dwHorseHealthDropTime, row[col++]); str_to_number(pkTab->horse.sStamina, row[col++]); str_to_number(pkTab->logoff_interval, row[col++]); str_to_number(pkTab->horse_skill_point, row[col++]); // reset sub_skill_point { pkTab->skills[123].bLevel = 0; // SKILL_CREATE if (pkTab->level > 9) { int max_point = pkTab->level - 9; int skill_point = MIN(20, pkTab->skills[121].bLevel) + // SKILL_LEADERSHIP Åë¼Ö·Â MIN(20, pkTab->skills[124].bLevel) + // SKILL_MINING 䱤 MIN(10, pkTab->skills[131].bLevel) + // SKILL_HORSE_SUMMON ¸»¼Òȯ MIN(20, pkTab->skills[141].bLevel) + // SKILL_ADD_HP HPº¸°­ MIN(20, pkTab->skills[142].bLevel); // SKILL_RESIST_PENETRATE °üÅëÀúÇ× pkTab->sub_skill_point = max_point - skill_point; } else pkTab->sub_skill_point = 0; } return true; } void CClientManager::RESULT_COMPOSITE_PLAYER(CPeer * peer, SQLMsg * pMsg, DWORD dwQID) { CQueryInfo * qi = (CQueryInfo *) pMsg->pvUserData; std::unique_ptr info((ClientHandleInfo *) qi->pvData); MYSQL_RES * pSQLResult = pMsg->Get()->pSQLResult; if (!pSQLResult) { sys_err("null MYSQL_RES QID %u", dwQID); return; } switch (dwQID) { case QID_PLAYER: sys_log(0, "QID_PLAYER %u %u", info->dwHandle, info->player_id); RESULT_PLAYER_LOAD(peer, pSQLResult, info.get()); break; case QID_ITEM: sys_log(0, "QID_ITEM %u", info->dwHandle); RESULT_ITEM_LOAD(peer, pSQLResult, info->dwHandle, info->player_id); break; case QID_QUEST: { sys_log(0, "QID_QUEST %u", info->dwHandle); RESULT_QUEST_LOAD(peer, pSQLResult, info->dwHandle, info->player_id); //aid¾ò±â ClientHandleInfo* temp1 = info.get(); if (temp1 == NULL) break; CLoginData* pLoginData1 = GetLoginDataByAID(temp1->account_id); // //µ¶ÀÏ ¼±¹° ±â´É if( pLoginData1->GetAccountRef().login == NULL) break; if( pLoginData1 == NULL ) break; sys_log(0,"info of pLoginData1 before call ItemAwardfunction %d",pLoginData1); ItemAward(peer,pLoginData1->GetAccountRef().login); } break; case QID_AFFECT: sys_log(0, "QID_AFFECT %u", info->dwHandle); RESULT_AFFECT_LOAD(peer, pSQLResult, info->dwHandle); break; /* case QID_PLAYER_ITEM_QUEST_AFFECT: sys_log(0, "QID_PLAYER_ITEM_QUEST_AFFECT %u", info->dwHandle); RESULT_PLAYER_LOAD(peer, pSQLResult, info->dwHandle); if (!pMsg->Next()) { sys_err("RESULT_COMPOSITE_PLAYER: QID_PLAYER_ITEM_QUEST_AFFECT: ITEM FAILED"); return; } case QID_ITEM_QUEST_AFFECT: sys_log(0, "QID_ITEM_QUEST_AFFECT %u", info->dwHandle); RESULT_ITEM_LOAD(peer, pSQLResult, info->dwHandle, info->player_id); if (!pMsg->Next()) { sys_err("RESULT_COMPOSITE_PLAYER: QID_PLAYER_ITEM_QUEST_AFFECT: QUEST FAILED"); return; } case QID_QUEST_AFFECT: sys_log(0, "QID_QUEST_AFFECT %u", info->dwHandle); RESULT_QUEST_LOAD(peer, pSQLResult, info->dwHandle); if (!pMsg->Next()) sys_err("RESULT_COMPOSITE_PLAYER: QID_PLAYER_ITEM_QUEST_AFFECT: AFFECT FAILED"); else RESULT_AFFECT_LOAD(peer, pSQLResult, info->dwHandle); break; */ } } void CClientManager::RESULT_PLAYER_LOAD(CPeer * peer, MYSQL_RES * pRes, ClientHandleInfo * pkInfo) { TPlayerTable tab; if (!CreatePlayerTableFromRes(pRes, &tab)) { peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_FAILED, pkInfo->dwHandle, 0); return; } CLoginData * pkLD = GetLoginDataByAID(pkInfo->account_id); if (!pkLD || pkLD->IsPlay()) { sys_log(0, "PLAYER_LOAD_ERROR: LoginData %p IsPlay %d", pkLD, pkLD ? pkLD->IsPlay() : 0); peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_FAILED, pkInfo->dwHandle, 0); return; } pkLD->SetPlay(true); SendLoginToBilling(pkLD, true); memcpy(tab.aiPremiumTimes, pkLD->GetPremiumPtr(), sizeof(tab.aiPremiumTimes)); peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_SUCCESS, pkInfo->dwHandle, sizeof(TPlayerTable)); peer->Encode(&tab, sizeof(TPlayerTable)); if (tab.id != pkLD->GetLastPlayerID()) { TPacketNeedLoginLogInfo logInfo; logInfo.dwPlayerID = tab.id; pkLD->SetLastPlayerID( tab.id ); peer->EncodeHeader( HEADER_DG_NEED_LOGIN_LOG, pkInfo->dwHandle, sizeof(TPacketNeedLoginLogInfo) ); peer->Encode( &logInfo, sizeof(TPacketNeedLoginLogInfo) ); } } void CClientManager::RESULT_ITEM_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle, DWORD dwPID) { static std::vector s_items; //DB¿¡¼­ ¾ÆÀÌÅÛ Á¤º¸¸¦ Àоî¿Â´Ù. CreateItemTableFromRes(pRes, &s_items, dwPID); DWORD dwCount = s_items.size(); peer->EncodeHeader(HEADER_DG_ITEM_LOAD, dwHandle, sizeof(DWORD) + sizeof(TPlayerItem) * dwCount); peer->EncodeDWORD(dwCount); //CacheSetÀ» ¸¸µç´Ù CreateItemCacheSet(dwPID); // ITEM_LOAD_LOG_ATTACH_PID sys_log(0, "ITEM_LOAD: count %u pid %u", dwCount, dwPID); // END_OF_ITEM_LOAD_LOG_ATTACH_PID if (dwCount) { peer->Encode(&s_items[0], sizeof(TPlayerItem) * dwCount); for (DWORD i = 0; i < dwCount; ++i) PutItemCache(&s_items[i], true); // ·ÎµåÇÑ °ÍÀº µû·Î ÀúÀåÇÒ ÇÊ¿ä ¾øÀ¸¹Ç·Î, ÀÎÀÚ bSkipQuery¿¡ true¸¦ ³Ö´Â´Ù. } } void CClientManager::RESULT_AFFECT_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle) { int iNumRows; if ((iNumRows = mysql_num_rows(pRes)) == 0) // µ¥ÀÌÅÍ ¾øÀ½ return; static std::vector s_elements; s_elements.resize(iNumRows); DWORD dwPID = 0; MYSQL_ROW row; for (int i = 0; i < iNumRows; ++i) { TPacketAffectElement & r = s_elements[i]; row = mysql_fetch_row(pRes); if (dwPID == 0) str_to_number(dwPID, row[0]); str_to_number(r.dwType, row[1]); str_to_number(r.bApplyOn, row[2]); str_to_number(r.lApplyValue, row[3]); str_to_number(r.dwFlag, row[4]); str_to_number(r.lDuration, row[5]); str_to_number(r.lSPCost, row[6]); } sys_log(0, "AFFECT_LOAD: count %d PID %u", s_elements.size(), dwPID); DWORD dwCount = s_elements.size(); peer->EncodeHeader(HEADER_DG_AFFECT_LOAD, dwHandle, sizeof(DWORD) + sizeof(DWORD) + sizeof(TPacketAffectElement) * dwCount); peer->Encode(&dwPID, sizeof(DWORD)); peer->Encode(&dwCount, sizeof(DWORD)); peer->Encode(&s_elements[0], sizeof(TPacketAffectElement) * dwCount); } void CClientManager::RESULT_QUEST_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle, DWORD pid) { int iNumRows; if ((iNumRows = mysql_num_rows(pRes)) == 0) { DWORD dwCount = 0; peer->EncodeHeader(HEADER_DG_QUEST_LOAD, dwHandle, sizeof(DWORD)); peer->Encode(&dwCount, sizeof(DWORD)); return; } static std::vector s_table; s_table.resize(iNumRows); MYSQL_ROW row; for (int i = 0; i < iNumRows; ++i) { TQuestTable & r = s_table[i]; row = mysql_fetch_row(pRes); str_to_number(r.dwPID, row[0]); strncpy(r.szName, row[1], sizeof(r.szName)); strncpy(r.szState, row[2], sizeof(r.szState)); str_to_number(r.lValue, row[3]); } sys_log(0, "QUEST_LOAD: count %d PID %u", s_table.size(), s_table[0].dwPID); DWORD dwCount = s_table.size(); peer->EncodeHeader(HEADER_DG_QUEST_LOAD, dwHandle, sizeof(DWORD) + sizeof(TQuestTable) * dwCount); peer->Encode(&dwCount, sizeof(DWORD)); peer->Encode(&s_table[0], sizeof(TQuestTable) * dwCount); } /* * PLAYER SAVE */ void CClientManager::QUERY_PLAYER_SAVE(CPeer * peer, DWORD dwHandle, TPlayerTable * pkTab) { if (g_test_server) sys_log(0, "PLAYER_SAVE: %s", pkTab->name); PutPlayerCache(pkTab); } typedef std::map time_by_id_map_t; static time_by_id_map_t s_createTimeByAccountID; /* * PLAYER CREATE */ void CClientManager::__QUERY_PLAYER_CREATE(CPeer *peer, DWORD dwHandle, TPlayerCreatePacket* packet) { char queryStr[QUERY_MAX_LEN]; int queryLen; DWORD player_id; // ÇÑ °èÁ¤¿¡ XÃÊ ³»·Î ij¸¯ÅÍ »ý¼ºÀ» ÇÒ ¼ö ¾ø´Ù. auto it = s_createTimeByAccountID.find(packet->account_id); if (it != s_createTimeByAccountID.end()) { time_t curtime = time(nullptr); if (curtime - it->second < 30) { peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0); return; } } queryLen = snprintf(queryStr, sizeof(queryStr), "SELECT pid%u FROM player_index%s WHERE id=%d", packet->account_index + 1, GetTablePostfix(), packet->account_id); std::unique_ptr pMsg0(CDBManager::instance().DirectQuery(queryStr)); if (pMsg0->Get()->uiNumRows != 0) { if (!pMsg0->Get()->pSQLResult) { peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0); return; } MYSQL_ROW row = mysql_fetch_row(pMsg0->Get()->pSQLResult); DWORD dwPID = 0; str_to_number(dwPID, row[0]); if (row[0] && dwPID > 0) { peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0); sys_log(0, "ALREADY EXIST AccountChrIdx %d ID %d", packet->account_index, dwPID); return; } } else { peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0); return; } if (g_stLocale == "sjis") snprintf(queryStr, sizeof(queryStr), "SELECT COUNT(*) as count FROM player%s WHERE name='%s' collate sjis_japanese_ci", GetTablePostfix(), packet->player_table.name); else snprintf(queryStr, sizeof(queryStr), "SELECT COUNT(*) as count FROM player%s WHERE name='%s'", GetTablePostfix(), packet->player_table.name); std::unique_ptr pMsg1(CDBManager::instance().DirectQuery(queryStr)); if (pMsg1->Get()->uiNumRows) { if (!pMsg1->Get()->pSQLResult) { peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0); return; } MYSQL_ROW row = mysql_fetch_row(pMsg1->Get()->pSQLResult); if (*row[0] != '0') { sys_log(0, "ALREADY EXIST name %s, row[0] %s query %s", packet->player_table.name, row[0], queryStr); peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0); return; } } else { peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0); return; } queryLen = snprintf(queryStr, sizeof(queryStr), "INSERT INTO player%s " "(id, account_id, name, level, st, ht, dx, iq, " "job, voice, dir, x, y, z, " "hp, mp, random_hp, random_sp, stat_point, stamina, part_base, part_main, part_hair, gold, playtime, " "skill_level, quickslot) " "VALUES(0, %u, '%s', %d, %d, %d, %d, %d, " "%d, %d, %d, %d, %d, %d, %d, " "%d, %d, %d, %d, %d, %d, %d, 0, %d, 0, ", GetTablePostfix(), packet->account_id, packet->player_table.name, packet->player_table.level, packet->player_table.st, packet->player_table.ht, packet->player_table.dx, packet->player_table.iq, packet->player_table.job, packet->player_table.voice, packet->player_table.dir, packet->player_table.x, packet->player_table.y, packet->player_table.z, packet->player_table.hp, packet->player_table.sp, packet->player_table.sRandomHP, packet->player_table.sRandomSP, packet->player_table.stat_point, packet->player_table.stamina, packet->player_table.part_base, packet->player_table.part_base, packet->player_table.gold); sys_log(0, "PlayerCreate accountid %d name %s level %d gold %d, st %d ht %d job %d", packet->account_id, packet->player_table.name, packet->player_table.level, packet->player_table.gold, packet->player_table.st, packet->player_table.ht, packet->player_table.job); char text[8192 + 1]; CDBManager::instance().EscapeString(text, packet->player_table.skills, sizeof(packet->player_table.skills)); queryLen += snprintf(queryStr + queryLen, sizeof(queryStr) - queryLen, "'%s', ", text); if (g_test_server) sys_log(0, "Create_Player queryLen[%d] TEXT[%s]", queryLen, text); CDBManager::instance().EscapeString(text, packet->player_table.quickslot, sizeof(packet->player_table.quickslot)); queryLen += snprintf(queryStr + queryLen, sizeof(queryStr) - queryLen, "'%s')", text); std::unique_ptr pMsg2(CDBManager::instance().DirectQuery(queryStr)); if (g_test_server) sys_log(0, "Create_Player queryLen[%d] TEXT[%s]", queryLen, text); if (pMsg2->Get()->uiAffectedRows <= 0) { peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0); sys_log(0, "ALREADY EXIST3 query: %s AffectedRows %lu", queryStr, pMsg2->Get()->uiAffectedRows); return; } player_id = pMsg2->Get()->uiInsertID; snprintf(queryStr, sizeof(queryStr), "UPDATE player_index%s SET pid%d=%d WHERE id=%d", GetTablePostfix(), packet->account_index + 1, player_id, packet->account_id); std::unique_ptr pMsg3(CDBManager::instance().DirectQuery(queryStr)); if (pMsg3->Get()->uiAffectedRows <= 0) { sys_err("QUERY_ERROR: %s", queryStr); snprintf(queryStr, sizeof(queryStr), "DELETE FROM player%s WHERE id=%d", GetTablePostfix(), player_id); CDBManager::instance().DirectQuery(queryStr); peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0); return; } TPacketDGCreateSuccess pack; memset(&pack, 0, sizeof(pack)); pack.bAccountCharacterIndex = packet->account_index; pack.player.dwID = player_id; strncpy(pack.player.szName, packet->player_table.name, sizeof(pack.player.szName)); pack.player.byJob = packet->player_table.job; pack.player.byLevel = 1; pack.player.dwPlayMinutes = 0; pack.player.byST = packet->player_table.st; pack.player.byHT = packet->player_table.ht; pack.player.byDX = packet->player_table.dx; pack.player.byIQ = packet->player_table.iq; pack.player.wMainPart = packet->player_table.part_base; pack.player.x = packet->player_table.x; pack.player.y = packet->player_table.y; peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_SUCCESS, dwHandle, sizeof(TPacketDGCreateSuccess)); peer->Encode(&pack, sizeof(TPacketDGCreateSuccess)); sys_log(0, "7 name %s job %d", pack.player.szName, pack.player.byJob); s_createTimeByAccountID[packet->account_id] = time(0); } /* * PLAYER DELETE */ void CClientManager::__QUERY_PLAYER_DELETE(CPeer* peer, DWORD dwHandle, TPlayerDeletePacket* packet) { if (!packet->login[0] || !packet->player_id || packet->account_index >= PLAYER_PER_ACCOUNT) return; CLoginData * ld = GetLoginDataByLogin(packet->login); if (!ld) { peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, dwHandle, 1); peer->EncodeBYTE(packet->account_index); return; } TAccountTable & r = ld->GetAccountRef(); // block for japan if (g_stLocale != "sjis") { if (!IsChinaEventServer()) { if (strlen(r.social_id) < 7 || strncmp(packet->private_code, r.social_id + strlen(r.social_id) - 7, 7)) { sys_log(0, "PLAYER_DELETE FAILED len(%d)", strlen(r.social_id)); peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, dwHandle, 1); peer->EncodeBYTE(packet->account_index); return; } CPlayerTableCache * pkPlayerCache = GetPlayerCache(packet->player_id); if (pkPlayerCache) { TPlayerTable * pTab = pkPlayerCache->Get(); if (pTab->level >= m_iPlayerDeleteLevelLimit) { sys_log(0, "PLAYER_DELETE FAILED LEVEL %u >= DELETE LIMIT %d", pTab->level, m_iPlayerDeleteLevelLimit); peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, dwHandle, 1); peer->EncodeBYTE(packet->account_index); return; } if (pTab->level < m_iPlayerDeleteLevelLimitLower) { sys_log(0, "PLAYER_DELETE FAILED LEVEL %u < DELETE LIMIT %d", pTab->level, m_iPlayerDeleteLevelLimitLower); peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, dwHandle, 1); peer->EncodeBYTE(packet->account_index); return; } } } } char szQuery[128]; snprintf(szQuery, sizeof(szQuery), "SELECT p.id, p.level, p.name FROM player_index%s AS i, player%s AS p WHERE pid%u=%u AND pid%u=p.id", GetTablePostfix(), GetTablePostfix(), packet->account_index + 1, packet->player_id, packet->account_index + 1); ClientHandleInfo * pi = new ClientHandleInfo(dwHandle, packet->player_id); pi->account_index = packet->account_index; sys_log(0, "PLAYER_DELETE TRY: %s %d pid%d", packet->login, packet->player_id, packet->account_index + 1); CDBManager::instance().ReturnQuery(szQuery, QID_PLAYER_DELETE, peer->GetHandle(), pi); } // // @version 05/06/10 Bang2ni - Ç÷¹ÀÌ¾î »èÁ¦½Ã °¡°ÝÁ¤º¸ ¸®½ºÆ® »èÁ¦ Ãß°¡. // void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg) { CQueryInfo * qi = (CQueryInfo *) msg->pvUserData; ClientHandleInfo * pi = (ClientHandleInfo *) qi->pvData; if (msg->Get() && msg->Get()->uiNumRows) { MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult); DWORD dwPID = 0; str_to_number(dwPID, row[0]); int deletedLevelLimit = 0; str_to_number(deletedLevelLimit, row[1]); char szName[64]; strncpy(szName, row[2], sizeof(szName)); if (deletedLevelLimit >= m_iPlayerDeleteLevelLimit && !IsChinaEventServer()) { sys_log(0, "PLAYER_DELETE FAILED LEVEL %u >= DELETE LIMIT %d", deletedLevelLimit, m_iPlayerDeleteLevelLimit); peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1); peer->EncodeBYTE(pi->account_index); return; } if (deletedLevelLimit < m_iPlayerDeleteLevelLimitLower) { sys_log(0, "PLAYER_DELETE FAILED LEVEL %u < DELETE LIMIT %d", deletedLevelLimit, m_iPlayerDeleteLevelLimitLower); peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1); peer->EncodeBYTE(pi->account_index); return; } char queryStr[QUERY_MAX_LEN]; snprintf(queryStr, sizeof(queryStr), "INSERT INTO player%s_deleted SELECT * FROM player%s WHERE id=%d", GetTablePostfix(), GetTablePostfix(), pi->player_id); std::unique_ptr pIns(CDBManager::instance().DirectQuery(queryStr)); if (pIns->Get()->uiAffectedRows == 0 || pIns->Get()->uiAffectedRows == (uint32_t)-1) { sys_log(0, "PLAYER_DELETE FAILED %u CANNOT INSERT TO player%s_deleted", dwPID, GetTablePostfix()); peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1); peer->EncodeBYTE(pi->account_index); return; } // »èÁ¦ ¼º°ø sys_log(0, "PLAYER_DELETE SUCCESS %u", dwPID); char account_index_string[16]; snprintf(account_index_string, sizeof(account_index_string), "player_id%d", m_iPlayerIDStart + pi->account_index); // Ç÷¹À̾î Å×À̺íÀ» ij½¬¿¡¼­ »èÁ¦ÇÑ´Ù. CPlayerTableCache * pkPlayerCache = GetPlayerCache(pi->player_id); if (pkPlayerCache) { m_map_playerCache.erase(pi->player_id); delete pkPlayerCache; } // ¾ÆÀÌÅÛµéÀ» ij½¬¿¡¼­ »èÁ¦ÇÑ´Ù. TItemCacheSet * pSet = GetItemCacheSet(pi->player_id); if (pSet) { TItemCacheSet::iterator it = pSet->begin(); while (it != pSet->end()) { CItemCache * pkItemCache = *it++; DeleteItemCache(pkItemCache->Get()->id); } pSet->clear(); delete pSet; m_map_pkItemCacheSetPtr.erase(pi->player_id); } snprintf(queryStr, sizeof(queryStr), "UPDATE player_index%s SET pid%u=0 WHERE pid%u=%d", GetTablePostfix(), pi->account_index + 1, pi->account_index + 1, pi->player_id); std::unique_ptr pMsg(CDBManager::instance().DirectQuery(queryStr)); if (pMsg->Get()->uiAffectedRows == 0 || pMsg->Get()->uiAffectedRows == (uint32_t)-1) { sys_log(0, "PLAYER_DELETE FAIL WHEN UPDATE account table"); peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1); peer->EncodeBYTE(pi->account_index); return; } snprintf(queryStr, sizeof(queryStr), "DELETE FROM player%s WHERE id=%d", GetTablePostfix(), pi->player_id); delete CDBManager::instance().DirectQuery(queryStr); snprintf(queryStr, sizeof(queryStr), "DELETE FROM item%s WHERE owner_id=%d AND (window < %d or window = %d)", GetTablePostfix(), pi->player_id, SAFEBOX, DRAGON_SOUL_INVENTORY); delete CDBManager::instance().DirectQuery(queryStr); snprintf(queryStr, sizeof(queryStr), "DELETE FROM quest%s WHERE dwPID=%d", GetTablePostfix(), pi->player_id); CDBManager::instance().AsyncQuery(queryStr); snprintf(queryStr, sizeof(queryStr), "DELETE FROM affect%s WHERE dwPID=%d", GetTablePostfix(), pi->player_id); CDBManager::instance().AsyncQuery(queryStr); snprintf(queryStr, sizeof(queryStr), "DELETE FROM guild_member%s WHERE pid=%d", GetTablePostfix(), pi->player_id); CDBManager::instance().AsyncQuery(queryStr); // MYSHOP_PRICE_LIST snprintf(queryStr, sizeof(queryStr), "DELETE FROM myshop_pricelist%s WHERE owner_id=%d", GetTablePostfix(), pi->player_id); CDBManager::instance().AsyncQuery(queryStr); // END_OF_MYSHOP_PRICE_LIST snprintf(queryStr, sizeof(queryStr), "DELETE FROM messenger_list%s WHERE account='%s' OR companion='%s'", GetTablePostfix(), szName, szName); CDBManager::instance().AsyncQuery(queryStr); peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_SUCCESS, pi->dwHandle, 1); peer->EncodeBYTE(pi->account_index); } else { // »èÁ¦ ½ÇÆÐ sys_log(0, "PLAYER_DELETE FAIL NO ROW"); peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1); peer->EncodeBYTE(pi->account_index); } } void CClientManager::QUERY_ADD_AFFECT(CPeer * peer, TPacketGDAddAffect * p) { char queryStr[QUERY_MAX_LEN]; /* snprintf(queryStr, sizeof(queryStr), "INSERT INTO affect%s (dwPID, bType, bApplyOn, lApplyValue, dwFlag, lDuration, lSPCost) " "VALUES(%u, %u, %u, %d, %u, %d, %d) " "ON DUPLICATE KEY UPDATE lApplyValue=%d, dwFlag=%u, lDuration=%d, lSPCost=%d", GetTablePostfix(), p->dwPID, p->elem.dwType, p->elem.bApplyOn, p->elem.lApplyValue, p->elem.dwFlag, p->elem.lDuration, p->elem.lSPCost, p->elem.lApplyValue, p->elem.dwFlag, p->elem.lDuration, p->elem.lSPCost); */ snprintf(queryStr, sizeof(queryStr), "REPLACE INTO affect%s (dwPID, bType, bApplyOn, lApplyValue, dwFlag, lDuration, lSPCost) " "VALUES(%u, %u, %u, %ld, %u, %ld, %ld)", GetTablePostfix(), p->dwPID, p->elem.dwType, p->elem.bApplyOn, p->elem.lApplyValue, p->elem.dwFlag, p->elem.lDuration, p->elem.lSPCost); CDBManager::instance().AsyncQuery(queryStr); } void CClientManager::QUERY_REMOVE_AFFECT(CPeer * peer, TPacketGDRemoveAffect * p) { char queryStr[QUERY_MAX_LEN]; snprintf(queryStr, sizeof(queryStr), "DELETE FROM affect%s WHERE dwPID=%u AND bType=%u AND bApplyOn=%u", GetTablePostfix(), p->dwPID, p->dwType, p->bApplyOn); CDBManager::instance().AsyncQuery(queryStr); } void CClientManager::QUERY_HIGHSCORE_REGISTER(CPeer* peer, TPacketGDHighscore * data) { char szQuery[128]; snprintf(szQuery, sizeof(szQuery), "SELECT value FROM highscore%s WHERE board='%s' AND pid = %u", GetTablePostfix(), data->szBoard, data->dwPID); sys_log(0, "HEADER_GD_HIGHSCORE_REGISTER: PID %u", data->dwPID); ClientHandleInfo * pi = new ClientHandleInfo(0); strncpy(pi->login, data->szBoard, sizeof(pi->login)); pi->account_id = (DWORD)data->lValue; pi->player_id = data->dwPID; pi->account_index = (data->cDir > 0); CDBManager::instance().ReturnQuery(szQuery, QID_HIGHSCORE_REGISTER, peer->GetHandle(), pi); } void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg) { CQueryInfo * qi = (CQueryInfo *) msg->pvUserData; ClientHandleInfo * pi = (ClientHandleInfo *) qi->pvData; //DWORD dwHandle = pi->dwHandle; char szBoard[21]; strncpy(szBoard, pi->login, sizeof(szBoard)); int value = (int)pi->account_id; SQLResult * res = msg->Get(); if (res->uiNumRows == 0) { // »õ·Î¿î ÇÏÀ̽ºÄھ »ðÀÔ char buf[256]; snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value); CDBManager::instance().AsyncQuery(buf); } else { if (!res->pSQLResult) { delete pi; return; } MYSQL_ROW row = mysql_fetch_row(res->pSQLResult); if (row && row[0]) { int current_value = 0; str_to_number(current_value, row[0]); if (pi->account_index && current_value >= value || !pi->account_index && current_value <= value) { value = current_value; } else { char buf[256]; snprintf(buf, sizeof(buf), "REPLACE INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value); CDBManager::instance().AsyncQuery(buf); } } else { char buf[256]; snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value); CDBManager::instance().AsyncQuery(buf); } } // TODO: ÀÌ°÷¿¡¼­ ÇÏÀ̽ºÄھ ¾÷µ¥ÀÌÆ® µÇ¾ú´ÂÁö üũÇÏ¿© °øÁö¸¦ »Ñ·Á¾ßÇÑ´Ù. delete pi; } void CClientManager::InsertLogoutPlayer(DWORD pid) { TLogoutPlayerMap::iterator it = m_map_logout.find(pid); // Á¸ÀçÇÏÁö ¾ÊÀ»°æ¿ì Ãß°¡ if (it != m_map_logout.end()) { // Á¸ÀçÇÒ°æ¿ì ½Ã°£¸¸ °»½Å if (g_log) sys_log(0, "LOGOUT: Update player time pid(%d)", pid); it->second->time = time(0); return; } TLogoutPlayer * pLogout = new TLogoutPlayer; pLogout->pid = pid; pLogout->time = time(0); m_map_logout.insert(std::make_pair(pid, pLogout)); if (g_log) sys_log(0, "LOGOUT: Insert player pid(%d)", pid); } void CClientManager::DeleteLogoutPlayer(DWORD pid) { TLogoutPlayerMap::iterator it = m_map_logout.find(pid); if (it != m_map_logout.end()) { delete it->second; m_map_logout.erase(it); } } extern int g_iLogoutSeconds; void CClientManager::UpdateLogoutPlayer() { time_t now = time(0); TLogoutPlayerMap::iterator it = m_map_logout.begin(); while (it != m_map_logout.end()) { TLogoutPlayer* pLogout = it->second; if (now - g_iLogoutSeconds > pLogout->time) { FlushItemCacheSet(pLogout->pid); FlushPlayerCacheSet(pLogout->pid); delete pLogout; m_map_logout.erase(it++); } else ++it; } } void CClientManager::FlushPlayerCacheSet(DWORD pid) { TPlayerTableCacheMap::iterator it = m_map_playerCache.find(pid); if (it != m_map_playerCache.end()) { CPlayerTableCache * c = it->second; m_map_playerCache.erase(it); c->Flush(); delete c; } }