Guest User

ClientManagerPlayer.cpp

a guest
Feb 15th, 2017
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 40.33 KB | None | 0 0
  1.  
  2. #include "stdafx.h"
  3.  
  4. #include "ClientManager.h"
  5.  
  6. #include "Main.h"
  7. #include "QID.h"
  8. #include "ItemAwardManager.h"
  9. #include "HB.h"
  10. #include "Cache.h"
  11.  
  12. extern bool g_bHotBackup;
  13.  
  14. extern std::string g_stLocale;
  15. extern int g_test_server;
  16. extern int g_log;
  17.  
  18. //
  19. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  20. // !!!!!!!!!!! IMPORTANT !!!!!!!!!!!!
  21. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  22. //
  23. // Check all SELECT syntax on item table before change this function!!!
  24. //
  25. bool CreateItemTableFromRes(MYSQL_RES * res, std::vector<TPlayerItem> * pVec, DWORD dwPID)
  26. {
  27.     if (!res)
  28.     {
  29.         pVec->clear();
  30.         return true;
  31.     }
  32.  
  33.     int rows;
  34.  
  35.     if ((rows = mysql_num_rows(res)) <= 0)  // 데이터 없음
  36.     {
  37.         pVec->clear();
  38.         return true;
  39.     }
  40.  
  41.     pVec->resize(rows);
  42.  
  43.     for (int i = 0; i < rows; ++i)
  44.     {
  45.         MYSQL_ROW row = mysql_fetch_row(res);
  46.         TPlayerItem & item = pVec->at(i);
  47.  
  48.         int cur = 0;
  49.  
  50.         // Check all SELECT syntax on item table before change this function!!!
  51.         // Check all SELECT syntax on item table before change this function!!!
  52.         // Check all SELECT syntax on item table before change this function!!!
  53.         str_to_number(item.id, row[cur++]);
  54.         str_to_number(item.window, row[cur++]);
  55.         str_to_number(item.pos, row[cur++]);
  56.         str_to_number(item.count, row[cur++]);
  57.         str_to_number(item.vnum, row[cur++]);
  58.         str_to_number(item.alSockets[0], row[cur++]);
  59.         str_to_number(item.alSockets[1], row[cur++]);
  60.         str_to_number(item.alSockets[2], row[cur++]);
  61.  
  62.         for (int j = 0; j < ITEM_ATTRIBUTE_MAX_NUM; j++)
  63.         {
  64.             str_to_number(item.aAttr[j].bType, row[cur++]);
  65.             str_to_number(item.aAttr[j].sValue, row[cur++]);
  66.         }
  67.  
  68.         item.owner      = dwPID;
  69.     }
  70.  
  71.     return true;
  72. }
  73.  
  74. size_t CreatePlayerSaveQuery(char * pszQuery, size_t querySize, TPlayerTable * pkTab)
  75. {
  76.     size_t queryLen;
  77.     queryLen = snprintf(pszQuery, querySize,
  78.             "UPDATE player%s SET "
  79.             "job = %d, "
  80.             "voice = %d, "
  81.             "dir = %d, "
  82.             "x = %d, "
  83.             "y = %d, "
  84.             "z = %d, "
  85.             "map_index = %d, "
  86.             "exit_x = %ld, "
  87.             "exit_y = %ld, "
  88.             "exit_map_index = %ld, "
  89.             "hp = %d, "
  90.             "mp = %d, "
  91.             "stamina = %d, "
  92.             "random_hp = %d, "
  93.             "random_sp = %d, "
  94.             "playtime = %d, "
  95.             "level = %d, "
  96.             "level_step = %d, "
  97.             "st = %d, "
  98.             "ht = %d, "
  99.             "dx = %d, "
  100.             "iq = %d, "
  101.             "gold = %d, "
  102.             "exp = %u, "
  103.             "stat_point = %d, "
  104.             "skill_point = %d, "
  105.             "sub_skill_point = %d, "
  106.             "stat_reset_count = %d, "
  107.             "ip = '%s', "
  108.             "part_main = %d, "
  109.             "part_hair = %d, "
  110.             "part_acce = %d, "
  111.             "last_play = NOW(), "
  112.             "skill_group = %d, "
  113.             "alignment = %ld, "
  114.             "horse_level = %d, "
  115.             "horse_riding = %d, "
  116.             "horse_hp = %d, "
  117.             "horse_hp_droptime = %u, "
  118.             "horse_stamina = %d, "
  119.             "horse_skill_point = %d, "
  120.             ,
  121.         GetTablePostfix(),
  122.         pkTab->job,
  123.         pkTab->voice,
  124.         pkTab->dir,
  125.         pkTab->x,
  126.         pkTab->y,
  127.         pkTab->z,
  128.         pkTab->lMapIndex,
  129.         pkTab->lExitX,
  130.         pkTab->lExitY,
  131.         pkTab->lExitMapIndex,
  132.         pkTab->hp,
  133.         pkTab->sp,
  134.         pkTab->stamina,
  135.         pkTab->sRandomHP,
  136.         pkTab->sRandomSP,
  137.         pkTab->playtime,
  138.         pkTab->level,
  139.         pkTab->level_step,
  140.         pkTab->st,
  141.         pkTab->ht,
  142.         pkTab->dx,
  143.         pkTab->iq,
  144.         pkTab->gold,
  145.         pkTab->exp,
  146.         pkTab->stat_point,
  147.         pkTab->skill_point,
  148.         pkTab->sub_skill_point,
  149.         pkTab->stat_reset_count,
  150.         pkTab->ip,
  151.         pkTab->parts[PART_MAIN],
  152.         pkTab->parts[PART_HAIR],
  153.         pkTab->parts[PART_ACCE],
  154.         pkTab->skill_group,
  155.         pkTab->lAlignment,
  156.         pkTab->horse.bLevel,
  157.         pkTab->horse.bRiding,
  158.         pkTab->horse.sHealth,
  159.         pkTab->horse.dwHorseHealthDropTime,
  160.         pkTab->horse.sStamina,
  161.         pkTab->horse_skill_point);
  162.    
  163.     static char text[8192 + 1];
  164.     CDBManager::instance().EscapeString(text, pkTab->skills, sizeof(pkTab->skills));
  165.     queryLen += snprintf(pszQuery + queryLen, querySize - queryLen, "skill_level = '%s', ", text);
  166.    
  167.     CDBManager::instance().EscapeString(text, pkTab->quickslot, sizeof(pkTab->quickslot));
  168.     queryLen += snprintf(pszQuery + queryLen, querySize - queryLen, "quickslot = '%s' ", text);
  169.    
  170.     queryLen += snprintf(pszQuery + queryLen, querySize - queryLen, " WHERE id=%d", pkTab->id);
  171.     return queryLen;
  172. }
  173.  
  174. CPlayerTableCache * CClientManager::GetPlayerCache(DWORD id)
  175. {
  176.     TPlayerTableCacheMap::iterator it = m_map_playerCache.find(id);
  177.  
  178.     if (it == m_map_playerCache.end())
  179.         return NULL;
  180.  
  181.     TPlayerTable* pTable = it->second->Get(false);
  182.     pTable->logoff_interval = GetCurrentTime() - it->second->GetLastUpdateTime();
  183.     return it->second;
  184. }
  185.  
  186. void CClientManager::PutPlayerCache(TPlayerTable * pNew)
  187. {
  188.     CPlayerTableCache * c;
  189.  
  190.     c = GetPlayerCache(pNew->id);
  191.  
  192.     if (!c)
  193.     {
  194.         c = new CPlayerTableCache;
  195.         m_map_playerCache.insert(TPlayerTableCacheMap::value_type(pNew->id, c));
  196.     }
  197.  
  198.     if (g_bHotBackup)
  199.         PlayerHB::instance().Put(pNew->id);
  200.  
  201.     c->Put(pNew);
  202. }
  203.  
  204. /*
  205.  * PLAYER LOAD
  206.  */
  207. void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoadPacket * packet)
  208. {
  209.     CPlayerTableCache * c;
  210.     TPlayerTable * pTab;
  211.    
  212.     CLoginData * pLoginData = GetLoginDataByAID(packet->account_id);
  213.     if (pLoginData)
  214.     {
  215.         for (int n = 0; n < PLAYER_PER_ACCOUNT; ++n)
  216.             if (pLoginData->GetAccountRef().players[n].dwID != 0)
  217.                 DeleteLogoutPlayer(pLoginData->GetAccountRef().players[n].dwID);
  218.     }
  219.    
  220.     if ((c = GetPlayerCache(packet->player_id)))
  221.     {
  222.         CLoginData * pkLD = GetLoginDataByAID(packet->account_id);
  223.         if (!pkLD || pkLD->IsPlay())
  224.         {
  225.             sys_log(0, "PLAYER_LOAD_ERROR: LoginData %p IsPlay %d", pkLD, pkLD ? pkLD->IsPlay() : 0);
  226.             peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_FAILED, dwHandle, 0);
  227.             return;
  228.         }
  229.        
  230.         pTab = c->Get();
  231.         pkLD->SetPlay(true);
  232.         SendLoginToBilling(pkLD, true);
  233.         thecore_memcpy(pTab->aiPremiumTimes, pkLD->GetPremiumPtr(), sizeof(pTab->aiPremiumTimes));
  234.        
  235.         peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_SUCCESS, dwHandle, sizeof(TPlayerTable));
  236.         peer->Encode(pTab, sizeof(TPlayerTable));
  237.        
  238.         if (packet->player_id != pkLD->GetLastPlayerID())
  239.         {
  240.             TPacketNeedLoginLogInfo logInfo;
  241.             logInfo.dwPlayerID = packet->player_id;
  242.            
  243.             pkLD->SetLastPlayerID(packet->player_id);
  244.             peer->EncodeHeader( HEADER_DG_NEED_LOGIN_LOG, dwHandle, sizeof(TPacketNeedLoginLogInfo) );
  245.             peer->Encode( &logInfo, sizeof(TPacketNeedLoginLogInfo) );
  246.         }
  247.        
  248.         char szQuery[1024] = { 0, };
  249.         TItemCacheSet * pSet = GetItemCacheSet(pTab->id);
  250.         sys_log(0, "[PLAYER_LOAD] ID %s pid %d gold %d ", pTab->name, pTab->id, pTab->gold);
  251.        
  252.         if (pSet)
  253.         {
  254.             static std::vector<TPlayerItem> s_items;
  255.             s_items.resize(pSet->size());
  256.            
  257.             DWORD dwCount = 0;
  258.             TItemCacheSet::iterator it = pSet->begin();
  259.             while (it != pSet->end())
  260.             {
  261.                 CItemCache * c = *it++;
  262.                 TPlayerItem * p = c->Get();
  263.  
  264.                 if (p->vnum)
  265.                     thecore_memcpy(&s_items[dwCount++], p, sizeof(TPlayerItem));
  266.             }
  267.            
  268.             if (g_test_server)
  269.                 sys_log(0, "ITEM_CACHE: HIT! %s count: %u", pTab->name, dwCount);
  270.            
  271.             peer->EncodeHeader(HEADER_DG_ITEM_LOAD, dwHandle, sizeof(DWORD) + sizeof(TPlayerItem) * dwCount);
  272.             peer->EncodeDWORD(dwCount);
  273.            
  274.             if (dwCount)
  275.                 peer->Encode(&s_items[0], sizeof(TPlayerItem) * dwCount);
  276.            
  277.             snprintf(szQuery, sizeof(szQuery),
  278.                     "SELECT dwPID,szName,szState,lValue FROM quest%s WHERE dwPID=%d AND lValue<>0",
  279.                     GetTablePostfix(), pTab->id);
  280.            
  281.             CDBManager::instance().ReturnQuery(szQuery, QID_QUEST, peer->GetHandle(), new ClientHandleInfo(dwHandle,0,packet->account_id));
  282.             snprintf(szQuery, sizeof(szQuery), "SELECT dwPID,bType,bApplyOn,lApplyValue,dwFlag,lDuration,lSPCost FROM affect%s WHERE dwPID=%d", GetTablePostfix(), pTab->id);
  283.             CDBManager::instance().ReturnQuery(szQuery, QID_AFFECT, peer->GetHandle(), new ClientHandleInfo(dwHandle));
  284.         }
  285.         else
  286.         {
  287.             snprintf(szQuery, sizeof(szQuery),
  288.                     "SELECT id,window+0,pos,count,vnum,socket0,socket1,socket2,attrtype0,attrvalue0,attrtype1,attrvalue1,attrtype2,attrvalue2,attrtype3,attrvalue3,attrtype4,attrvalue4,attrtype5,attrvalue5,attrtype6,attrvalue6,applytype0,applyvalue0,applytype1,applyvalue1,applytype2,applyvalue2,applytype3,applyvalue3,applytype4,applyvalue4,applytype5,applyvalue5,applytype6,applyvalue6,applytype7,applyvalue7 "
  289.                     "FROM item%s WHERE owner_id=%d AND (window < %d or window = %d)",
  290.                     GetTablePostfix(), pTab->id, SAFEBOX, DRAGON_SOUL_INVENTORY);
  291.            
  292.             CDBManager::instance().ReturnQuery(szQuery, QID_ITEM, peer->GetHandle(), new ClientHandleInfo(dwHandle, pTab->id));
  293.             snprintf(szQuery, sizeof(szQuery), "SELECT dwPID, szName, szState, lValue FROM quest%s WHERE dwPID=%d", GetTablePostfix(), pTab->id);
  294.  
  295.             CDBManager::instance().ReturnQuery(szQuery, QID_QUEST, peer->GetHandle(), new ClientHandleInfo(dwHandle, pTab->id));
  296.             snprintf(szQuery, sizeof(szQuery), "SELECT dwPID, bType, bApplyOn, lApplyValue, dwFlag, lDuration, lSPCost FROM affect%s WHERE dwPID=%d", GetTablePostfix(), pTab->id);
  297.            
  298.             CDBManager::instance().ReturnQuery(szQuery, QID_AFFECT, peer->GetHandle(), new ClientHandleInfo(dwHandle, pTab->id));
  299.         }
  300.     }
  301.     else
  302.     {
  303.         sys_log(0, "[PLAYER_LOAD] Load from PlayerDB pid[%d]", packet->player_id);
  304.         char queryStr[QUERY_MAX_LEN];
  305.         snprintf(queryStr, sizeof(queryStr),
  306.                 "SELECT "
  307.                 "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,"
  308.                 "gold,level,level_step,st,ht,dx,iq,exp,"
  309.                 "stat_point,skill_point,sub_skill_point,stat_reset_count,part_base,part_hair,part_acce,"
  310.                 "skill_level,quickslot,skill_group,alignment,mobile,horse_level,horse_riding,horse_hp,horse_hp_droptime,horse_stamina,"
  311.                 "UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(last_play),horse_skill_point,prestige_level FROM player%s WHERE id=%d",
  312.                 GetTablePostfix(), packet->player_id);
  313.        
  314.         ClientHandleInfo * pkInfo = new ClientHandleInfo(dwHandle, packet->player_id);
  315.         pkInfo->account_id = packet->account_id;
  316.         CDBManager::instance().ReturnQuery(queryStr, QID_PLAYER, peer->GetHandle(), pkInfo);
  317.        
  318.         snprintf(queryStr, sizeof(queryStr),
  319.                 "SELECT id,window+0,pos,count,vnum,socket0,socket1,socket2,attrtype0,attrvalue0,attrtype1,attrvalue1,attrtype2,attrvalue2,attrtype3,attrvalue3,attrtype4,attrvalue4,attrtype5,attrvalue5,attrtype6,attrvalue6,applytype0,applyvalue0,applytype1,applyvalue1,applytype2,applyvalue2,applytype3,applyvalue3,applytype4,applyvalue4,applytype5,applyvalue5,applytype6,applyvalue6,applytype7,applyvalue7 "
  320.                 "FROM item%s WHERE owner_id=%d AND (window < %d or window = %d)",
  321.                 GetTablePostfix(), packet->player_id, SAFEBOX, DRAGON_SOUL_INVENTORY);
  322.        
  323.         CDBManager::instance().ReturnQuery(queryStr, QID_ITEM, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id));
  324.        
  325.         snprintf(queryStr, sizeof(queryStr),
  326.                 "SELECT dwPID,szName,szState,lValue FROM quest%s WHERE dwPID=%d",
  327.                 GetTablePostfix(), packet->player_id);
  328.         CDBManager::instance().ReturnQuery(queryStr, QID_QUEST, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id,packet->account_id));
  329.        
  330.         snprintf(queryStr, sizeof(queryStr),
  331.                 "SELECT dwPID,bType,bApplyOn,lApplyValue,dwFlag,lDuration,lSPCost FROM affect%s WHERE dwPID=%d",
  332.                 GetTablePostfix(), packet->player_id);
  333.         CDBManager::instance().ReturnQuery(queryStr, QID_AFFECT, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id));
  334.     }
  335. }
  336.  
  337. void CClientManager::ItemAward(CPeer * peer,char* login)
  338. {
  339.     char login_t[LOGIN_MAX_LEN + 1] = "";
  340.     strlcpy(login_t,login,LOGIN_MAX_LEN + 1);  
  341.     std::set<TItemAward *> * pSet = ItemAwardManager::instance().GetByLogin(login_t);  
  342.     if(pSet == NULL)
  343.         return;
  344.     typeof(pSet->begin()) it = pSet->begin();   //taken_time이 NULL인것들 읽어옴
  345.     while(it != pSet->end() )
  346.     {              
  347.         TItemAward * pItemAward = *(it++);     
  348.         char* whyStr = pItemAward->szWhy;   //why 콜룸 읽기
  349.         char cmdStr[100] = "";  //why콜룸에서 읽은 값을 임시 문자열에 복사해둠
  350.         strcpy(cmdStr,whyStr);  //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문
  351.         char command[20] = "";
  352.         strcpy(command,GetCommand(cmdStr)); // command 얻기      
  353.         if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면
  354.         {
  355.             TPacketItemAwardInfromer giftData;
  356.             strcpy(giftData.login, pItemAward->szLogin);    //로그인 아이디 복사
  357.             strcpy(giftData.command, command);                  //명령어 복사
  358.             giftData.vnum = pItemAward->dwVnum;             //아이템 vnum도 복사
  359.             ForwardPacket(HEADER_DG_ITEMAWARD_INFORMER,&giftData,sizeof(TPacketItemAwardInfromer));
  360.         }
  361.     }
  362. }
  363. char* CClientManager::GetCommand(char* str)
  364. {
  365.     char command[20] = "";
  366.     char* tok;
  367.  
  368.     if( str[0] == '[' )
  369.     {
  370.         tok = strtok(str,"]");         
  371.         strcat(command,&tok[1]);       
  372.     }
  373.  
  374.     return command;
  375. }
  376.  
  377. bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab)
  378. {
  379.     if (mysql_num_rows(res) == 0)
  380.         return false;
  381.    
  382.     memset(pkTab, 0, sizeof(TPlayerTable));
  383.     MYSQL_ROW row = mysql_fetch_row(res);
  384.     int col = 0;
  385.    
  386.     str_to_number(pkTab->id, row[col++]);
  387.     strlcpy(pkTab->name, row[col++], sizeof(pkTab->name));
  388.     str_to_number(pkTab->job, row[col++]);
  389.     str_to_number(pkTab->voice, row[col++]);
  390.     str_to_number(pkTab->dir, row[col++]);
  391.     str_to_number(pkTab->x, row[col++]);
  392.     str_to_number(pkTab->y, row[col++]);
  393.     str_to_number(pkTab->z, row[col++]);
  394.     str_to_number(pkTab->lMapIndex, row[col++]);
  395.     str_to_number(pkTab->lExitX, row[col++]);
  396.     str_to_number(pkTab->lExitY, row[col++]);
  397.     str_to_number(pkTab->lExitMapIndex,  row[col++]);
  398.     str_to_number(pkTab->hp, row[col++]);
  399.     str_to_number(pkTab->sp, row[col++]);
  400.     str_to_number(pkTab->stamina, row[col++]);
  401.     str_to_number(pkTab->sRandomHP, row[col++]);
  402.     str_to_number(pkTab->sRandomSP, row[col++]);
  403.     str_to_number(pkTab->playtime, row[col++]);
  404.     str_to_number(pkTab->gold, row[col++]);
  405.     str_to_number(pkTab->level, row[col++]);
  406.     str_to_number(pkTab->level_step, row[col++]);
  407.     str_to_number(pkTab->st, row[col++]);
  408.     str_to_number(pkTab->ht, row[col++]);
  409.     str_to_number(pkTab->dx, row[col++]);
  410.     str_to_number(pkTab->iq, row[col++]);
  411.     str_to_number(pkTab->exp, row[col++]);
  412.     str_to_number(pkTab->stat_point, row[col++]);
  413.     str_to_number(pkTab->skill_point, row[col++]);
  414.     str_to_number(pkTab->sub_skill_point, row[col++]);
  415.     str_to_number(pkTab->stat_reset_count, row[col++]);
  416.     str_to_number(pkTab->part_base, row[col++]);
  417.     str_to_number(pkTab->parts[PART_HAIR], row[col++]);
  418.     str_to_number(pkTab->parts[PART_ACCE], row[col++]);
  419.     if (row[col])
  420.         thecore_memcpy(pkTab->skills, row[col], sizeof(pkTab->skills));
  421.     else
  422.         memset(&pkTab->skills, 0, sizeof(pkTab->skills));
  423.    
  424.     col++;
  425.    
  426.     if (row[col])
  427.         thecore_memcpy(pkTab->quickslot, row[col], sizeof(pkTab->quickslot));
  428.     else
  429.         memset(pkTab->quickslot, 0, sizeof(pkTab->quickslot));
  430.    
  431.     col++;
  432.    
  433.     str_to_number(pkTab->skill_group, row[col++]);
  434.     str_to_number(pkTab->lAlignment, row[col++]);
  435.     if (row[col])
  436.     {
  437.         strlcpy(pkTab->szMobile, row[col], sizeof(pkTab->szMobile));
  438.     }
  439.    
  440.     col++;
  441.     str_to_number(pkTab->horse.bLevel, row[col++]);
  442.     str_to_number(pkTab->horse.bRiding, row[col++]);
  443.     str_to_number(pkTab->horse.sHealth, row[col++]);
  444.     str_to_number(pkTab->horse.dwHorseHealthDropTime, row[col++]);
  445.     str_to_number(pkTab->horse.sStamina, row[col++]);
  446.     str_to_number(pkTab->logoff_interval, row[col++]);
  447.     str_to_number(pkTab->horse_skill_point, row[col++]);
  448.     {
  449.         pkTab->skills[123].bLevel = 0;
  450.         if (pkTab->level > 9)
  451.         {
  452.             int max_point = pkTab->level - 9;
  453.             int skill_point = MIN(20, pkTab->skills[121].bLevel) + MIN(20, pkTab->skills[124].bLevel) + MIN(10, pkTab->skills[131].bLevel) + MIN(20, pkTab->skills[141].bLevel) + MIN(20, pkTab->skills[142].bLevel);
  454.             pkTab->sub_skill_point = max_point - skill_point;
  455.         }
  456.         else
  457.             pkTab->sub_skill_point = 0;
  458.     }
  459.    
  460.     return true;
  461. }
  462.  
  463. void CClientManager::RESULT_COMPOSITE_PLAYER(CPeer * peer, SQLMsg * pMsg, DWORD dwQID)
  464. {
  465.     CQueryInfo * qi = (CQueryInfo *) pMsg->pvUserData;
  466.     std::auto_ptr<ClientHandleInfo> info((ClientHandleInfo *) qi->pvData);
  467.    
  468.     MYSQL_RES * pSQLResult = pMsg->Get()->pSQLResult;
  469.     if (!pSQLResult)
  470.     {
  471.         sys_err("null MYSQL_RES QID %u", dwQID);
  472.         return;
  473.     }
  474.  
  475.     switch (dwQID)
  476.     {
  477.         case QID_PLAYER:
  478.             sys_log(0, "QID_PLAYER %u %u", info->dwHandle, info->player_id);
  479.             RESULT_PLAYER_LOAD(peer, pSQLResult, info.get());
  480.  
  481.             break;
  482.  
  483.         case QID_ITEM:
  484.             sys_log(0, "QID_ITEM %u", info->dwHandle);
  485.             RESULT_ITEM_LOAD(peer, pSQLResult, info->dwHandle, info->player_id);
  486.             break;
  487.  
  488.         case QID_QUEST:
  489.             {
  490.                 sys_log(0, "QID_QUEST %u", info->dwHandle);
  491.                 RESULT_QUEST_LOAD(peer, pSQLResult, info->dwHandle, info->player_id);
  492.                 //aid얻기
  493.                 ClientHandleInfo*  temp1 = info.get();
  494.                 if (temp1 == NULL)
  495.                     break;
  496.                
  497.                 CLoginData* pLoginData1 = GetLoginDataByAID(temp1->account_id); //             
  498.                 //독일 선물 기능
  499.                 if( pLoginData1->GetAccountRef().login == NULL)
  500.                     break;
  501.                 if( pLoginData1 == NULL )
  502.                     break;
  503.                 sys_log(0,"info of pLoginData1 before call ItemAwardfunction %d",pLoginData1);
  504.                 ItemAward(peer,pLoginData1->GetAccountRef().login);
  505.             }
  506.             break;
  507.  
  508.         case QID_AFFECT:
  509.             sys_log(0, "QID_AFFECT %u", info->dwHandle);
  510.             RESULT_AFFECT_LOAD(peer, pSQLResult, info->dwHandle);
  511.             break;
  512.             /*
  513.                case QID_PLAYER_ITEM_QUEST_AFFECT:
  514.                sys_log(0, "QID_PLAYER_ITEM_QUEST_AFFECT %u", info->dwHandle);
  515.                RESULT_PLAYER_LOAD(peer, pSQLResult, info->dwHandle);
  516.  
  517.                if (!pMsg->Next())
  518.                {
  519.                sys_err("RESULT_COMPOSITE_PLAYER: QID_PLAYER_ITEM_QUEST_AFFECT: ITEM FAILED");
  520.                return;
  521.                }
  522.  
  523.                case QID_ITEM_QUEST_AFFECT:
  524.                sys_log(0, "QID_ITEM_QUEST_AFFECT %u", info->dwHandle);
  525.                RESULT_ITEM_LOAD(peer, pSQLResult, info->dwHandle, info->player_id);
  526.  
  527.                if (!pMsg->Next())
  528.                {
  529.                sys_err("RESULT_COMPOSITE_PLAYER: QID_PLAYER_ITEM_QUEST_AFFECT: QUEST FAILED");
  530.                return;
  531.                }
  532.  
  533.                case QID_QUEST_AFFECT:
  534.                sys_log(0, "QID_QUEST_AFFECT %u", info->dwHandle);
  535.                RESULT_QUEST_LOAD(peer, pSQLResult, info->dwHandle);
  536.  
  537.                if (!pMsg->Next())
  538.                sys_err("RESULT_COMPOSITE_PLAYER: QID_PLAYER_ITEM_QUEST_AFFECT: AFFECT FAILED");
  539.                else
  540.                RESULT_AFFECT_LOAD(peer, pSQLResult, info->dwHandle);
  541.  
  542.                break;
  543.                */
  544.     }
  545.    
  546. }
  547.  
  548. void CClientManager::RESULT_PLAYER_LOAD(CPeer * peer, MYSQL_RES * pRes, ClientHandleInfo * pkInfo)
  549. {
  550.     TPlayerTable tab;
  551.  
  552.     if (!CreatePlayerTableFromRes(pRes, &tab))
  553.     {
  554.         peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_FAILED, pkInfo->dwHandle, 0);
  555.         return;
  556.     }
  557.  
  558.     CLoginData * pkLD = GetLoginDataByAID(pkInfo->account_id);
  559.    
  560.     if (!pkLD || pkLD->IsPlay())
  561.     {
  562.         sys_log(0, "PLAYER_LOAD_ERROR: LoginData %p IsPlay %d", pkLD, pkLD ? pkLD->IsPlay() : 0);
  563.         peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_FAILED, pkInfo->dwHandle, 0);
  564.         return;
  565.     }
  566.  
  567.     pkLD->SetPlay(true);
  568.     SendLoginToBilling(pkLD, true);
  569.     thecore_memcpy(tab.aiPremiumTimes, pkLD->GetPremiumPtr(), sizeof(tab.aiPremiumTimes));
  570.  
  571.     peer->EncodeHeader(HEADER_DG_PLAYER_LOAD_SUCCESS, pkInfo->dwHandle, sizeof(TPlayerTable));
  572.     peer->Encode(&tab, sizeof(TPlayerTable));
  573.  
  574.     if (tab.id != pkLD->GetLastPlayerID())
  575.     {
  576.         TPacketNeedLoginLogInfo logInfo;
  577.         logInfo.dwPlayerID = tab.id;
  578.  
  579.         pkLD->SetLastPlayerID( tab.id );
  580.  
  581.         peer->EncodeHeader( HEADER_DG_NEED_LOGIN_LOG, pkInfo->dwHandle, sizeof(TPacketNeedLoginLogInfo) );
  582.         peer->Encode( &logInfo, sizeof(TPacketNeedLoginLogInfo) );
  583.     }
  584. }
  585.  
  586. void CClientManager::RESULT_ITEM_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle, DWORD dwPID)
  587. {
  588.     static std::vector<TPlayerItem> s_items;
  589.     //DB에서 아이템 정보를 읽어온다.
  590.     CreateItemTableFromRes(pRes, &s_items, dwPID);
  591.     DWORD dwCount = s_items.size();
  592.  
  593.     peer->EncodeHeader(HEADER_DG_ITEM_LOAD, dwHandle, sizeof(DWORD) + sizeof(TPlayerItem) * dwCount);
  594.     peer->EncodeDWORD(dwCount);
  595.  
  596.     //CacheSet을 만든다  
  597.     CreateItemCacheSet(dwPID);
  598.  
  599.     // ITEM_LOAD_LOG_ATTACH_PID
  600.     sys_log(0, "ITEM_LOAD: count %u pid %u", dwCount, dwPID);
  601.     // END_OF_ITEM_LOAD_LOG_ATTACH_PID
  602.  
  603.     if (dwCount)
  604.     {
  605.         peer->Encode(&s_items[0], sizeof(TPlayerItem) * dwCount);
  606.  
  607.         for (DWORD i = 0; i < dwCount; ++i)
  608.             PutItemCache(&s_items[i], true); // 로드한 것은 따로 저장할 필요 없으므로, 인자 bSkipQuery에 true를 넣는다.
  609.     }
  610. }
  611.  
  612. void CClientManager::RESULT_AFFECT_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle)
  613. {
  614.     int iNumRows;
  615.  
  616.     if ((iNumRows = mysql_num_rows(pRes)) == 0) // 데이터 없음
  617.         return;
  618.  
  619.     static std::vector<TPacketAffectElement> s_elements;
  620.     s_elements.resize(iNumRows);
  621.  
  622.     DWORD dwPID = 0;
  623.  
  624.     MYSQL_ROW row;
  625.  
  626.     for (int i = 0; i < iNumRows; ++i)
  627.     {
  628.         TPacketAffectElement & r = s_elements[i];
  629.         row = mysql_fetch_row(pRes);
  630.  
  631.         if (dwPID == 0)
  632.             str_to_number(dwPID, row[0]);
  633.  
  634.         str_to_number(r.dwType, row[1]);
  635.         str_to_number(r.bApplyOn, row[2]);
  636.         str_to_number(r.lApplyValue, row[3]);
  637.         str_to_number(r.dwFlag, row[4]);
  638.         str_to_number(r.lDuration, row[5]);
  639.         str_to_number(r.lSPCost, row[6]);
  640.     }
  641.  
  642.     sys_log(0, "AFFECT_LOAD: count %d PID %u", s_elements.size(), dwPID);
  643.  
  644.     DWORD dwCount = s_elements.size();
  645.  
  646.     peer->EncodeHeader(HEADER_DG_AFFECT_LOAD, dwHandle, sizeof(DWORD) + sizeof(DWORD) + sizeof(TPacketAffectElement) * dwCount);
  647.     peer->Encode(&dwPID, sizeof(DWORD));
  648.     peer->Encode(&dwCount, sizeof(DWORD));
  649.     peer->Encode(&s_elements[0], sizeof(TPacketAffectElement) * dwCount);
  650. }
  651.  
  652. void CClientManager::RESULT_QUEST_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle, DWORD pid)
  653. {
  654.     int iNumRows;
  655.  
  656.     if ((iNumRows = mysql_num_rows(pRes)) == 0)
  657.     {
  658.         DWORD dwCount = 0;
  659.         peer->EncodeHeader(HEADER_DG_QUEST_LOAD, dwHandle, sizeof(DWORD));
  660.         peer->Encode(&dwCount, sizeof(DWORD));
  661.         return;
  662.     }
  663.  
  664.     static std::vector<TQuestTable> s_table;
  665.     s_table.resize(iNumRows);
  666.  
  667.     MYSQL_ROW row;
  668.  
  669.     for (int i = 0; i < iNumRows; ++i)
  670.     {
  671.         TQuestTable & r = s_table[i];
  672.  
  673.         row = mysql_fetch_row(pRes);
  674.  
  675.         str_to_number(r.dwPID, row[0]);
  676.         strlcpy(r.szName, row[1], sizeof(r.szName));
  677.         strlcpy(r.szState, row[2], sizeof(r.szState));
  678.         str_to_number(r.lValue, row[3]);
  679.     }
  680.  
  681.     sys_log(0, "QUEST_LOAD: count %d PID %u", s_table.size(), s_table[0].dwPID);
  682.  
  683.     DWORD dwCount = s_table.size();
  684.  
  685.     peer->EncodeHeader(HEADER_DG_QUEST_LOAD, dwHandle, sizeof(DWORD) + sizeof(TQuestTable) * dwCount);
  686.     peer->Encode(&dwCount, sizeof(DWORD));
  687.     peer->Encode(&s_table[0], sizeof(TQuestTable) * dwCount);
  688. }
  689.  
  690. /*
  691.  * PLAYER SAVE
  692.  */
  693. void CClientManager::QUERY_PLAYER_SAVE(CPeer * peer, DWORD dwHandle, TPlayerTable * pkTab)
  694. {
  695.     if (g_test_server)
  696.         sys_log(0, "PLAYER_SAVE: %s", pkTab->name);
  697.  
  698.     PutPlayerCache(pkTab);
  699. }
  700.  
  701. typedef std::map<DWORD, time_t> time_by_id_map_t;
  702. static time_by_id_map_t s_createTimeByAccountID;
  703.  
  704. /*
  705.  * PLAYER CREATE
  706.  */
  707. void CClientManager::__QUERY_PLAYER_CREATE(CPeer *peer, DWORD dwHandle, TPlayerCreatePacket* packet)
  708. {
  709.     char    queryStr[QUERY_MAX_LEN];
  710.     int     queryLen;
  711.     int     player_id;
  712.    
  713.     time_by_id_map_t::iterator it = s_createTimeByAccountID.find(packet->account_id);
  714.     if (it != s_createTimeByAccountID.end())
  715.     {
  716.         time_t curtime = time(0);
  717.         if (curtime - it->second < 30)
  718.         {
  719.             peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
  720.             return;
  721.         }
  722.     }
  723.    
  724.     queryLen = snprintf(queryStr, sizeof(queryStr), "SELECT pid%u FROM player_index%s WHERE id=%d", packet->account_index + 1, GetTablePostfix(), packet->account_id);
  725.     std::auto_ptr<SQLMsg> pMsg0(CDBManager::instance().DirectQuery(queryStr));
  726.     if (pMsg0->Get()->uiNumRows != 0)
  727.     {
  728.         if (!pMsg0->Get()->pSQLResult)
  729.         {
  730.             peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
  731.             return;
  732.         }
  733.        
  734.         MYSQL_ROW row = mysql_fetch_row(pMsg0->Get()->pSQLResult);
  735.         DWORD dwPID = 0; str_to_number(dwPID, row[0]);
  736.         if (row[0] && dwPID > 0)
  737.         {
  738.             peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0);
  739.             sys_log(0, "ALREADY EXIST AccountChrIdx %d ID %d", packet->account_index, dwPID);
  740.             return;
  741.         }
  742.     }
  743.     else
  744.     {
  745.         peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
  746.         return;
  747.     }
  748.    
  749.     if (g_stLocale == "sjis")
  750.         snprintf(queryStr, sizeof(queryStr), "SELECT COUNT(*) as count FROM player%s WHERE name='%s' collate sjis_japanese_ci", GetTablePostfix(), packet->player_table.name); 
  751.     else
  752.         snprintf(queryStr, sizeof(queryStr), "SELECT COUNT(*) as count FROM player%s WHERE name='%s'", GetTablePostfix(), packet->player_table.name);
  753.    
  754.     std::auto_ptr<SQLMsg> pMsg1(CDBManager::instance().DirectQuery(queryStr));
  755.     if (pMsg1->Get()->uiNumRows)
  756.     {
  757.         if (!pMsg1->Get()->pSQLResult)
  758.         {
  759.             peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
  760.             return;
  761.         }
  762.        
  763.         MYSQL_ROW row = mysql_fetch_row(pMsg1->Get()->pSQLResult);
  764.         if (*row[0] != '0')
  765.         {
  766.             sys_log(0, "ALREADY EXIST name %s, row[0] %s query %s", packet->player_table.name, row[0], queryStr);
  767.             peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0);
  768.             return;
  769.         }
  770.     }
  771.     else
  772.     {
  773.         peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
  774.         return;
  775.     }
  776.    
  777.     queryLen = snprintf(queryStr, sizeof(queryStr),
  778.             "INSERT INTO player%s "
  779.             "(id, account_id, name, level, st, ht, dx, iq, "
  780.             "job, voice, dir, x, y, z, "
  781.             "hp, mp, random_hp, random_sp, stat_point, stamina, part_base, part_main, part_hair, part_acce, gold, playtime, "
  782.             "skill_level, quickslot) "
  783.             "VALUES(0, %u, '%s', %d, %d, %d, %d, %d, "
  784.             "%d, %d, %d, %d, %d, %d, %d, "
  785.             "%d, %d, %d, %d, %d, %d, %d, %d, 0, %d, 0, ",
  786.             GetTablePostfix(),
  787.             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,
  788.             packet->player_table.job, packet->player_table.voice, packet->player_table.dir, packet->player_table.x, packet->player_table.y, packet->player_table.z,
  789.             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.part_base, packet->player_table.gold);
  790.    
  791.     sys_log(0, "PlayerCreate accountid %d name %s level %d gold %d, st %d ht %d job %d",
  792.             packet->account_id,
  793.             packet->player_table.name,
  794.             packet->player_table.level,
  795.             packet->player_table.gold,
  796.             packet->player_table.st,
  797.             packet->player_table.ht,
  798.             packet->player_table.job);
  799.    
  800.     static char text[4096 + 1];
  801.    
  802.     CDBManager::instance().EscapeString(text, packet->player_table.skills, sizeof(packet->player_table.skills));
  803.     queryLen += snprintf(queryStr + queryLen, sizeof(queryStr) - queryLen, "'%s', ", text);
  804.     if (g_test_server)
  805.         sys_log(0, "Create_Player queryLen[%d] TEXT[%s]", queryLen, text);
  806.    
  807.     CDBManager::instance().EscapeString(text, packet->player_table.quickslot, sizeof(packet->player_table.quickslot));
  808.     queryLen += snprintf(queryStr + queryLen, sizeof(queryStr) - queryLen, "'%s')", text);
  809.    
  810.     std::auto_ptr<SQLMsg> pMsg2(CDBManager::instance().DirectQuery(queryStr));
  811.     if (g_test_server)
  812.         sys_log(0, "Create_Player queryLen[%d] TEXT[%s]", queryLen, text);
  813.    
  814.     if (pMsg2->Get()->uiAffectedRows <= 0)
  815.     {
  816.         peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0);
  817.         sys_log(0, "ALREADY EXIST3 query: %s AffectedRows %lu", queryStr, pMsg2->Get()->uiAffectedRows);
  818.         return;
  819.     }
  820.    
  821.     player_id = pMsg2->Get()->uiInsertID;
  822.    
  823.     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);
  824.     std::auto_ptr<SQLMsg> pMsg3(CDBManager::instance().DirectQuery(queryStr));
  825.     if (pMsg3->Get()->uiAffectedRows <= 0)
  826.     {
  827.         sys_err("QUERY_ERROR: %s", queryStr);
  828.        
  829.         snprintf(queryStr, sizeof(queryStr), "DELETE FROM player%s WHERE id=%d", GetTablePostfix(), player_id);
  830.         CDBManager::instance().DirectQuery(queryStr);
  831.        
  832.         peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
  833.         return;
  834.     }
  835.    
  836.     TPacketDGCreateSuccess pack;
  837.     memset(&pack, 0, sizeof(pack));
  838.    
  839.     pack.bAccountCharacterIndex = packet->account_index;
  840.     pack.player.dwID = player_id;
  841.     strlcpy(pack.player.szName, packet->player_table.name, sizeof(pack.player.szName));
  842.     pack.player.byJob = packet->player_table.job;
  843.     pack.player.byLevel = 1;
  844.     pack.player.dwPlayMinutes = 0;
  845.     pack.player.byST = packet->player_table.st;
  846.     pack.player.byHT = packet->player_table.ht;
  847.     pack.player.byDX = packet->player_table.dx;
  848.     pack.player.byIQ = packet->player_table.iq;
  849.     pack.player.wMainPart = packet->player_table.part_base;
  850.     pack.player.x = packet->player_table.x;
  851.     pack.player.y = packet->player_table.y;
  852.    
  853.     peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_SUCCESS, dwHandle, sizeof(TPacketDGCreateSuccess));
  854.     peer->Encode(&pack, sizeof(TPacketDGCreateSuccess));
  855.    
  856.     sys_log(0, "7 name %s job %d", pack.player.szName, pack.player.byJob);
  857.     s_createTimeByAccountID[packet->account_id] = time(0);
  858. }
  859.  
  860. /*
  861.  * PLAYER DELETE
  862.  */
  863. void CClientManager::__QUERY_PLAYER_DELETE(CPeer* peer, DWORD dwHandle, TPlayerDeletePacket* packet)
  864. {
  865.     if (!packet->login[0] || !packet->player_id || packet->account_index >= PLAYER_PER_ACCOUNT)
  866.         return;
  867.  
  868.     CLoginData * ld = GetLoginDataByLogin(packet->login);
  869.  
  870.     if (!ld)
  871.     {
  872.         peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, dwHandle, 1);
  873.         peer->EncodeBYTE(packet->account_index);
  874.         return;
  875.     }
  876.  
  877.     TAccountTable & r = ld->GetAccountRef();
  878.  
  879.     // block for japan
  880.     if (g_stLocale != "sjis")
  881.     {
  882.         if (!IsChinaEventServer())
  883.         {
  884.             if (strlen(r.social_id) < 7 || strncmp(packet->private_code, r.social_id + strlen(r.social_id) - 7, 7))
  885.             {
  886.                 sys_log(0, "PLAYER_DELETE FAILED len(%d)", strlen(r.social_id));
  887.                 peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, dwHandle, 1);
  888.                 peer->EncodeBYTE(packet->account_index);
  889.                 return;
  890.             }
  891.  
  892.             CPlayerTableCache * pkPlayerCache = GetPlayerCache(packet->player_id);
  893.             if (pkPlayerCache)
  894.             {
  895.                 TPlayerTable * pTab = pkPlayerCache->Get();
  896.  
  897.                 if (pTab->level >= m_iPlayerDeleteLevelLimit)
  898.                 {
  899.                     sys_log(0, "PLAYER_DELETE FAILED LEVEL %u >= DELETE LIMIT %d", pTab->level, m_iPlayerDeleteLevelLimit);
  900.                     peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, dwHandle, 1);
  901.                     peer->EncodeBYTE(packet->account_index);
  902.                     return;
  903.                 }
  904.  
  905.                 if (pTab->level < m_iPlayerDeleteLevelLimitLower)
  906.                 {
  907.                     sys_log(0, "PLAYER_DELETE FAILED LEVEL %u < DELETE LIMIT %d", pTab->level, m_iPlayerDeleteLevelLimitLower);
  908.                     peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, dwHandle, 1);
  909.                     peer->EncodeBYTE(packet->account_index);
  910.                     return;
  911.                 }
  912.             }
  913.         }
  914.     }
  915.  
  916.     char szQuery[128];
  917.     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",
  918.             GetTablePostfix(), GetTablePostfix(), packet->account_index + 1, packet->player_id, packet->account_index + 1);
  919.  
  920.     ClientHandleInfo * pi = new ClientHandleInfo(dwHandle, packet->player_id);
  921.     pi->account_index = packet->account_index;
  922.  
  923.     sys_log(0, "PLAYER_DELETE TRY: %s %d pid%d", packet->login, packet->player_id, packet->account_index + 1);
  924.     CDBManager::instance().ReturnQuery(szQuery, QID_PLAYER_DELETE, peer->GetHandle(), pi);
  925. }
  926.  
  927. //
  928. // @version 05/06/10 Bang2ni - 플레이어 삭제시 가격정보 리스트 삭제 추가.
  929. //
  930. void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
  931. {
  932.     CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
  933.     ClientHandleInfo * pi = (ClientHandleInfo *) qi->pvData;
  934.  
  935.     if (msg->Get() && msg->Get()->uiNumRows)
  936.     {
  937.         MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult);
  938.  
  939.         DWORD dwPID = 0;
  940.         str_to_number(dwPID, row[0]);
  941.  
  942.         int deletedLevelLimit = 0;
  943.         str_to_number(deletedLevelLimit, row[1]);
  944.  
  945.         char szName[64];
  946.         strlcpy(szName, row[2], sizeof(szName));
  947.  
  948.         if (deletedLevelLimit >= m_iPlayerDeleteLevelLimit && !IsChinaEventServer())
  949.         {
  950.             sys_log(0, "PLAYER_DELETE FAILED LEVEL %u >= DELETE LIMIT %d", deletedLevelLimit, m_iPlayerDeleteLevelLimit);
  951.             peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
  952.             peer->EncodeBYTE(pi->account_index);
  953.             return;
  954.         }
  955.  
  956.         if (deletedLevelLimit < m_iPlayerDeleteLevelLimitLower)
  957.         {
  958.             sys_log(0, "PLAYER_DELETE FAILED LEVEL %u < DELETE LIMIT %d", deletedLevelLimit, m_iPlayerDeleteLevelLimitLower);
  959.             peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
  960.             peer->EncodeBYTE(pi->account_index);
  961.             return;
  962.         }
  963.  
  964.         char queryStr[QUERY_MAX_LEN];
  965.  
  966.         snprintf(queryStr, sizeof(queryStr), "INSERT INTO player%s_deleted SELECT * FROM player%s WHERE id=%d",
  967.                 GetTablePostfix(), GetTablePostfix(), pi->player_id);
  968.         std::auto_ptr<SQLMsg> pIns(CDBManager::instance().DirectQuery(queryStr));
  969.  
  970.         if (pIns->Get()->uiAffectedRows == 0 || pIns->Get()->uiAffectedRows == (uint32_t)-1)
  971.         {
  972.             sys_log(0, "PLAYER_DELETE FAILED %u CANNOT INSERT TO player%s_deleted", dwPID, GetTablePostfix());
  973.  
  974.             peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
  975.             peer->EncodeBYTE(pi->account_index);
  976.             return;
  977.         }
  978.  
  979.         // 삭제 성공
  980.         sys_log(0, "PLAYER_DELETE SUCCESS %u", dwPID);
  981.  
  982.         char account_index_string[16];
  983.  
  984.         snprintf(account_index_string, sizeof(account_index_string), "player_id%d", m_iPlayerIDStart + pi->account_index);
  985.  
  986.         // 플레이어 테이블을 캐쉬에서 삭제한다.
  987.         CPlayerTableCache * pkPlayerCache = GetPlayerCache(pi->player_id);
  988.  
  989.         if (pkPlayerCache)
  990.         {
  991.             m_map_playerCache.erase(pi->player_id);
  992.             delete pkPlayerCache;
  993.         }
  994.  
  995.         // 아이템들을 캐쉬에서 삭제한다.
  996.         TItemCacheSet * pSet = GetItemCacheSet(pi->player_id);
  997.  
  998.         if (pSet)
  999.         {
  1000.             TItemCacheSet::iterator it = pSet->begin();
  1001.  
  1002.             while (it != pSet->end())
  1003.             {
  1004.                 CItemCache * pkItemCache = *it++;
  1005.                 DeleteItemCache(pkItemCache->Get()->id);
  1006.             }
  1007.  
  1008.             pSet->clear();
  1009.             delete pSet;
  1010.  
  1011.             m_map_pkItemCacheSetPtr.erase(pi->player_id);
  1012.         }
  1013.  
  1014.         snprintf(queryStr, sizeof(queryStr), "UPDATE player_index%s SET pid%u=0 WHERE pid%u=%d",
  1015.                 GetTablePostfix(),
  1016.                 pi->account_index + 1,
  1017.                 pi->account_index + 1,
  1018.                 pi->player_id);
  1019.  
  1020.         std::auto_ptr<SQLMsg> pMsg(CDBManager::instance().DirectQuery(queryStr));
  1021.  
  1022.         if (pMsg->Get()->uiAffectedRows == 0 || pMsg->Get()->uiAffectedRows == (uint32_t)-1)
  1023.         {
  1024.             sys_log(0, "PLAYER_DELETE FAIL WHEN UPDATE account table");
  1025.             peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
  1026.             peer->EncodeBYTE(pi->account_index);
  1027.             return;
  1028.         }
  1029.  
  1030.         snprintf(queryStr, sizeof(queryStr), "DELETE FROM player%s WHERE id=%d", GetTablePostfix(), pi->player_id);
  1031.         delete CDBManager::instance().DirectQuery(queryStr);
  1032.  
  1033.         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);
  1034.         delete CDBManager::instance().DirectQuery(queryStr);
  1035.  
  1036.         snprintf(queryStr, sizeof(queryStr), "DELETE FROM quest%s WHERE dwPID=%d", GetTablePostfix(), pi->player_id);
  1037.         CDBManager::instance().AsyncQuery(queryStr);
  1038.  
  1039.         snprintf(queryStr, sizeof(queryStr), "DELETE FROM affect%s WHERE dwPID=%d", GetTablePostfix(), pi->player_id);
  1040.         CDBManager::instance().AsyncQuery(queryStr);
  1041.  
  1042.         snprintf(queryStr, sizeof(queryStr), "DELETE FROM guild_member%s WHERE pid=%d", GetTablePostfix(), pi->player_id);
  1043.         CDBManager::instance().AsyncQuery(queryStr);
  1044.  
  1045.         // MYSHOP_PRICE_LIST
  1046.         snprintf(queryStr, sizeof(queryStr), "DELETE FROM myshop_pricelist%s WHERE owner_id=%d", GetTablePostfix(), pi->player_id);
  1047.         CDBManager::instance().AsyncQuery(queryStr);
  1048.         // END_OF_MYSHOP_PRICE_LIST
  1049.  
  1050.         snprintf(queryStr, sizeof(queryStr), "DELETE FROM messenger_list%s WHERE account='%s' OR companion='%s'", GetTablePostfix(), szName, szName);
  1051.         CDBManager::instance().AsyncQuery(queryStr);
  1052.  
  1053.         peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_SUCCESS, pi->dwHandle, 1);
  1054.         peer->EncodeBYTE(pi->account_index);
  1055.     }
  1056.     else
  1057.     {
  1058.         // 삭제 실패
  1059.         sys_log(0, "PLAYER_DELETE FAIL NO ROW");
  1060.         peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
  1061.         peer->EncodeBYTE(pi->account_index);
  1062.     }
  1063. }
  1064.  
  1065. void CClientManager::QUERY_ADD_AFFECT(CPeer * peer, TPacketGDAddAffect * p)
  1066. {
  1067.     char queryStr[QUERY_MAX_LEN];
  1068.     /*
  1069.        snprintf(queryStr, sizeof(queryStr),
  1070.        "INSERT INTO affect%s (dwPID, bType, bApplyOn, lApplyValue, dwFlag, lDuration, lSPCost) "
  1071.        "VALUES(%u, %u, %u, %d, %u, %d, %d) "
  1072.        "ON DUPLICATE KEY UPDATE lApplyValue=%d, dwFlag=%u, lDuration=%d, lSPCost=%d",
  1073.        GetTablePostfix(),
  1074.        p->dwPID,
  1075.        p->elem.dwType,
  1076.        p->elem.bApplyOn,
  1077.        p->elem.lApplyValue,
  1078.        p->elem.dwFlag,
  1079.        p->elem.lDuration,
  1080.        p->elem.lSPCost,
  1081.        p->elem.lApplyValue,
  1082.        p->elem.dwFlag,
  1083.        p->elem.lDuration,
  1084.        p->elem.lSPCost);
  1085.        */
  1086.     snprintf(queryStr, sizeof(queryStr),
  1087.             "REPLACE INTO affect%s (dwPID, bType, bApplyOn, lApplyValue, dwFlag, lDuration, lSPCost) "
  1088.             "VALUES(%u, %u, %u, %ld, %u, %ld, %ld)",
  1089.             GetTablePostfix(),
  1090.             p->dwPID,
  1091.             p->elem.dwType,
  1092.             p->elem.bApplyOn,
  1093.             p->elem.lApplyValue,
  1094.             p->elem.dwFlag,
  1095.             p->elem.lDuration,
  1096.             p->elem.lSPCost);
  1097.  
  1098.     CDBManager::instance().AsyncQuery(queryStr);
  1099. }
  1100.  
  1101. void CClientManager::QUERY_REMOVE_AFFECT(CPeer * peer, TPacketGDRemoveAffect * p)
  1102. {
  1103.     char queryStr[QUERY_MAX_LEN];
  1104.  
  1105.     snprintf(queryStr, sizeof(queryStr),
  1106.             "DELETE FROM affect%s WHERE dwPID=%u AND bType=%u AND bApplyOn=%u",
  1107.             GetTablePostfix(), p->dwPID, p->dwType, p->bApplyOn);
  1108.  
  1109.     CDBManager::instance().AsyncQuery(queryStr);
  1110. }
  1111.  
  1112.  
  1113. void CClientManager::QUERY_HIGHSCORE_REGISTER(CPeer* peer, TPacketGDHighscore * data)
  1114. {
  1115.     char szQuery[128];
  1116.     snprintf(szQuery, sizeof(szQuery), "SELECT value FROM highscore%s WHERE board='%s' AND pid = %u", GetTablePostfix(), data->szBoard, data->dwPID);
  1117.  
  1118.     sys_log(0, "HEADER_GD_HIGHSCORE_REGISTER: PID %u", data->dwPID);
  1119.  
  1120.     ClientHandleInfo * pi = new ClientHandleInfo(0);
  1121.     strlcpy(pi->login, data->szBoard, sizeof(pi->login));
  1122.     pi->account_id = (DWORD)data->lValue;
  1123.     pi->player_id = data->dwPID;
  1124.     pi->account_index = (data->cDir > 0);
  1125.  
  1126.     CDBManager::instance().ReturnQuery(szQuery, QID_HIGHSCORE_REGISTER, peer->GetHandle(), pi);
  1127. }
  1128.  
  1129. void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg)
  1130. {
  1131.     CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
  1132.     ClientHandleInfo * pi = (ClientHandleInfo *) qi->pvData;
  1133.     //DWORD dwHandle = pi->dwHandle;
  1134.  
  1135.     char szBoard[21];
  1136.     strlcpy(szBoard, pi->login, sizeof(szBoard));
  1137.     int value = (int)pi->account_id;
  1138.  
  1139.     SQLResult * res = msg->Get();
  1140.  
  1141.     if (res->uiNumRows == 0)
  1142.     {
  1143.         // 새로운 하이스코어를 삽입
  1144.         char buf[256];
  1145.         snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value);
  1146.         CDBManager::instance().AsyncQuery(buf);
  1147.     }
  1148.     else
  1149.     {
  1150.         if (!res->pSQLResult)
  1151.         {
  1152.             delete pi;
  1153.             return;
  1154.         }
  1155.  
  1156.         MYSQL_ROW row = mysql_fetch_row(res->pSQLResult);
  1157.         if (row && row[0])
  1158.         {
  1159.             int current_value = 0; str_to_number(current_value, row[0]);
  1160.             if (pi->account_index && current_value >= value || !pi->account_index && current_value <= value)
  1161.             {
  1162.                 value = current_value;
  1163.             }
  1164.             else
  1165.             {
  1166.                 char buf[256];
  1167.                 snprintf(buf, sizeof(buf), "REPLACE INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value);
  1168.                 CDBManager::instance().AsyncQuery(buf);
  1169.             }
  1170.         }
  1171.         else
  1172.         {
  1173.             char buf[256];
  1174.             snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value);
  1175.             CDBManager::instance().AsyncQuery(buf);
  1176.         }
  1177.     }
  1178.     // TODO: 이곳에서 하이스코어가 업데이트 되었는지 체크하여 공지를 뿌려야한다.
  1179.     delete pi;
  1180. }
  1181.  
  1182. void CClientManager::InsertLogoutPlayer(DWORD pid)
  1183. {
  1184.     TLogoutPlayerMap::iterator it = m_map_logout.find(pid);
  1185.  
  1186.     // 존재하지 않을경우 추가
  1187.     if (it != m_map_logout.end())
  1188.     {
  1189.         // 존재할경우 시간만 갱신
  1190.         if (g_log)
  1191.             sys_log(0, "LOGOUT: Update player time pid(%d)", pid);
  1192.  
  1193.         it->second->time = time(0);
  1194.         return;
  1195.     }
  1196.        
  1197.     TLogoutPlayer * pLogout = new TLogoutPlayer;
  1198.     pLogout->pid = pid;
  1199.     pLogout->time = time(0);
  1200.     m_map_logout.insert(std::make_pair(pid, pLogout));
  1201.  
  1202.     if (g_log)
  1203.         sys_log(0, "LOGOUT: Insert player pid(%d)", pid);
  1204. }
  1205.  
  1206. void CClientManager::DeleteLogoutPlayer(DWORD pid)
  1207. {
  1208.     TLogoutPlayerMap::iterator it = m_map_logout.find(pid);
  1209.  
  1210.     if (it != m_map_logout.end())
  1211.     {
  1212.         delete it->second;
  1213.         m_map_logout.erase(it);
  1214.     }
  1215. }
  1216.  
  1217. extern int g_iLogoutSeconds;
  1218.  
  1219. void CClientManager::UpdateLogoutPlayer()
  1220. {
  1221.     time_t now = time(0);
  1222.  
  1223.     TLogoutPlayerMap::iterator it = m_map_logout.begin();
  1224.  
  1225.     while (it != m_map_logout.end())
  1226.     {
  1227.         TLogoutPlayer* pLogout = it->second;
  1228.  
  1229.         if (now - g_iLogoutSeconds > pLogout->time)
  1230.         {
  1231.             FlushItemCacheSet(pLogout->pid);
  1232.             FlushPlayerCacheSet(pLogout->pid);
  1233.  
  1234.             delete pLogout;
  1235.             m_map_logout.erase(it++);
  1236.         }
  1237.         else
  1238.             ++it;
  1239.     }
  1240. }
  1241.  
  1242. void CClientManager::FlushPlayerCacheSet(DWORD pid)
  1243. {
  1244.     TPlayerTableCacheMap::iterator it = m_map_playerCache.find(pid);
  1245.  
  1246.     if (it != m_map_playerCache.end())
  1247.     {
  1248.         CPlayerTableCache * c = it->second;
  1249.         m_map_playerCache.erase(it);
  1250.  
  1251.         c->Flush();
  1252.         delete c;
  1253.     }
  1254. }
Add Comment
Please, Sign In to add comment