// GiveEventReward.cpp : ÄÜ¼Ö ÀÀ¿ë ÇÁ·Î±×·¥¿¡ ´ëÇÑ ÁøÀÔÁ¡À» Á¤ÀÇÇÕ´Ï´Ù. // #include "stdafx.h" #pragma warning(disable:4800) #include #include #include #include #include #include #include #include #include #include #include #include class CGiveEventReward : public IDBCharItemProcess, public IDBCharItemExProcess, public IDBStoreProcess { public: typedef std::pair EventItem; typedef std::vector EventItemList; typedef std::pair > GiveItem; typedef std::vector GiveItemList; typedef std::multimap, boost::fast_pool_allocator > > GiveItemMap; CGiveEventReward(CDBItemSerialMgr& dbItemSerialMgr, Item::CItemMgr& newItemMgr); virtual ConvertResult operator()(RylDBCommand::CCharItem& charItem_InOut); virtual ConvertResult operator()(RylDBCommand::CCharItemEx& charItemEx_InOut); virtual ConvertResult operator()(RylDBCommand::CUnifiedStore1& unifiedStore1_InOut); virtual ConvertResult operator()(RylDBCommand::CUnifiedStore2& unifiedStore2_InOut); bool LoadScript(const char* szScriptFileName); // µ¥ÀÌÅÍ¿¡¼­ ¾ÆÀÌÅÛÀ» Á¦°ÅÇϰí Ä«¿îÆÃÇÑ´Ù. void RemoveItemFromContainer(unsigned long dwUID, unsigned long dwCID, RebalanceLib::CItemChecker* lpItemChecker, const char* szPosition, const char* szData_In, unsigned long dwDataSize_In, char* szData_Out, unsigned long& dwDataSize_Out); // ¾ÆÀÌÅÛÀ» ã¾Æ¼­ ³Ö¾î ÁØ´Ù. void GiveItemToContainer(unsigned long dwUID, unsigned long dwCID, RebalanceLib::CItemChecker& itemChecker, const char* szPosition, char* szData_InOut, unsigned long& dwDataSize_InOut, unsigned long dwMaxDataSize, bool bLastChance = false); private: CDBItemSerialMgr& m_DBItemSerialMgr; Item::CItemMgr& m_newItemMgr; EventItemList m_EventItemList; // first : Á¦°ÅÇÒ ¾ÆÀÌÅÛ ID / second : ÁÙ ¾ÆÀÌÅÛ Key GiveItemList m_GiveItemList; // first : ÁÙ ¾ÆÀÌÅÛ Key / second : ÁÙ ¾ÆÀÌÅÛ / ÁÙ ¾ÆÀÌÅÛ °³¼ö GiveItemMap m_CIDGiveItemMap; // first : CID / second : ÁÙ ¾ÆÀÌÅÛ / ÁÙ ¾ÆÀÌÅÛ °³¼ö GiveItemMap m_UIDGiveItemMap; // first : UID / second : ÁÙ ¾ÆÀÌÅÛ / ÁÙ ¾ÆÀÌÅÛ °³¼ö }; void PrintUsage() { printf("usage : GiveEventReward.exe DBAddress DBName DBAccount DBPassword " "ServerGroupNum(0~9) RewardScriptName \n"); } int _tmain(int argc, _TCHAR* argv[]) { if(7 != argc) { PrintUsage(); return -1; } int nServerGroup = atoi(argv[5]); const char* szRewardScriptName = argv[6]; // ¾ÆÀÌÅÛ ½ºÅ©¸³Æ® ·Îµå if(!Item::CItemMgr::GetInstance().LoadItemProtoType("./NewItemScript.txt")) { printf("NewItemScript.txt load failed\n"); return -1; } CDBItemSerialMgr dbItemSerialMgr; CGiveEventReward giveEventReward(dbItemSerialMgr, Item::CItemMgr::GetInstance()); // À̺¥Æ® º¸»ó ½ºÅ©¸³Æ® ·Îµå if(!giveEventReward.LoadScript(szRewardScriptName)) { printf("%s load failed\n", szRewardScriptName); return -1; } CoInitialize(0); SERVER_ID serverID; serverID.sID.Type = CServerSetup::AuthServer; serverID.sID.Group = nServerGroup; serverID.sID.Channel = 0; serverID.sID.ID = 0; HRESULT hr = S_OK; ATL::CDataSource dataSource; ATL::CSession Session; #define LOG_CONVERT0(str) { ERRLOG0(g_Log, (str)); printf(str "\n"); } #define LOG_CONVERT1(str, arg1) { ERRLOG1(g_Log, (str), (arg1)); printf(str "\n", (arg1)); } #define LOG_CONVERT2(str, arg1, arg2) { ERRLOG2(g_Log, (str), (arg1), (arg2)); printf(str "\n", (arg1), (arg2)); } if(FAILED(hr = CRylDBProcess::ConnectDB(dataSource, argv[1], argv[2], argv[3], argv[4]))) { LOG_CONVERT1("Connect DB failed : hr:0x%08X", hr); } else if(FAILED(hr = Session.Open(dataSource))) { LOG_CONVERT1("Open session failed : hr:0x%08X", hr); } else if(FAILED(hr = dbItemSerialMgr.LoadItemSerialDB(Session, serverID.dwID))) { LOG_CONVERT1("Insert itemSerial failed : hr:0x%08X", hr); } else { CRylDBProcess rylDBProcess(Session); CConsoleCounter consoleCounter(1000); if (!rylDBProcess.UnifiedStore1(giveEventReward, consoleCounter)) { LOG_CONVERT1("UnifiedStore1 process failed : hr:0x%08X", hr); } else if (!rylDBProcess.UnifiedStore2(giveEventReward, consoleCounter)) { LOG_CONVERT1("UnifiedStore2 process failed : hr:0x%08X", hr); } else if (!rylDBProcess.CharItem(giveEventReward, consoleCounter)) { LOG_CONVERT1("CharItem process failed : hr:0x%08X", hr); } else if (!rylDBProcess.CharItemEx(giveEventReward, consoleCounter)) { LOG_CONVERT1("CharItemEx process failed : hr:0x%08X", hr); } // ¾ÆÀÌÅÛ ½Ã¸®¾ó ÃÖÁ¾ ÀúÀå else if(FAILED(hr = dbItemSerialMgr.SaveItemSerialDB(Session, serverID.dwID))) { LOG_CONVERT1("ItemSerial save failed : hr:0x%08X", hr); } } INFLOG0(g_Log, "Give Complete"); Session.Close(); dataSource.Close(); CoUninitialize(); return 0; } CGiveEventReward::CGiveEventReward(CDBItemSerialMgr& dbItemSerialMgr, Item::CItemMgr& newItemMgr) : m_DBItemSerialMgr(dbItemSerialMgr), m_newItemMgr(newItemMgr) { } ConvertResult CGiveEventReward::operator()(RylDBCommand::CCharItem& charItem_InOut) { unsigned long dwCID = charItem_InOut.GetCID(); const EQUIP& equip_In = charItem_InOut.GetEquip(); const INVEN& inven_In = charItem_InOut.GetInven(); const EXTRA& extra_In = charItem_InOut.GetExtra(); EQUIP equip_Out; INVEN inven_Out; EXTRA extra_Out; memset(&equip_Out, 0, sizeof(EQUIP)); memset(&inven_Out, 0, sizeof(INVEN)); memset(&extra_Out, 0, sizeof(EXTRA)); RebalanceLib::CItemArrayChecker< ContainerConstant::INVENTORY_WIDTH, ContainerConstant::INVENTORY_HEIGHT, ContainerConstant::MAX_INVENTORY_TAB> inven_checker(TakeType::TS_INVEN); RemoveItemFromContainer(0, dwCID, 0, "EQUIP", equip_In.Data, equip_In.dwSize, equip_Out.Data, equip_Out.dwSize); RemoveItemFromContainer(0, dwCID, &inven_checker, "INVEN", inven_In.Data, inven_In.dwSize, inven_Out.Data, inven_Out.dwSize); RemoveItemFromContainer(0, dwCID, 0, "EXTRA", extra_In.Data, extra_In.dwSize, extra_Out.Data, extra_Out.dwSize); GiveItemToContainer(0, dwCID, inven_checker, "INVEN", inven_Out.Data, inven_Out.dwSize, INVEN::MAX_INVEN_SIZE); charItem_InOut.SetEquip(equip_Out); charItem_InOut.SetInven(inven_Out); charItem_InOut.SetExtra(extra_Out); return CONVERT_SUCCEEDED; } ConvertResult CGiveEventReward::operator()(RylDBCommand::CCharItemEx& charItemEx_InOut) { unsigned long dwCID = charItemEx_InOut.GetCID(); const EXCHANGE& exchange_In = charItemEx_InOut.GetExchange(); const TEMPINVEN& tempInven_In = charItemEx_InOut.GetTempInven(); EXCHANGE exchange_Out; TEMPINVEN tempInven_Out; memset(&exchange_Out, 0, sizeof(EXCHANGE)); memset(&tempInven_Out, 0, sizeof(TEMPINVEN)); RebalanceLib::CItemListChecker tempInvenChecker(TakeType::TS_TEMPINVEN); RemoveItemFromContainer(0, dwCID, 0, "EXCHANGE", exchange_In.Data, exchange_In.dwSize, exchange_Out.Data, exchange_Out.dwSize); RemoveItemFromContainer(0, dwCID, &tempInvenChecker, "TEMPINVEN", tempInven_In.Data, tempInven_In.dwSize, tempInven_Out.Data, tempInven_Out.dwSize); // LAST Chance! GiveItemToContainer(0, dwCID, tempInvenChecker, "TEMPINVEN", tempInven_Out.Data, tempInven_Out.dwSize, TEMPINVEN::MAX_TEMPINVEN_SIZE, true); charItemEx_InOut.SetExchange(exchange_Out); charItemEx_InOut.SetTempInven(tempInven_Out); return CONVERT_SUCCEEDED; } ConvertResult CGiveEventReward::operator()(RylDBCommand::CUnifiedStore1& unifiedStore1_InOut) { unsigned long dwUID = unifiedStore1_InOut.GetUID(); const STORE& store_In = unifiedStore1_InOut.GetStore(); STORE store_Out; memset(&store_Out, 0, sizeof(STORE)); RebalanceLib::CItemArrayChecker< ContainerConstant::DEPOSIT_WIDTH, ContainerConstant::DEPOSIT_HEIGHT, ContainerConstant::MAX_DEPOSIT_TAB> depositChecker(TakeType::TS_DEPOSIT); depositChecker.FillTab(2); depositChecker.FillTab(3); RemoveItemFromContainer(dwUID, 0, &depositChecker, "UNIFIED_STORE_01", store_In.Data, store_In.dwSize, store_Out.Data, store_Out.dwSize); GiveItemToContainer(dwUID, 0, depositChecker, "UnifiedStore1", store_Out.Data, store_Out.dwSize, STORE::MAX_STORE_SIZE); unifiedStore1_InOut.SetStore(store_Out); return CONVERT_SUCCEEDED; } ConvertResult CGiveEventReward::operator()(RylDBCommand::CUnifiedStore2& unifiedStore2_InOut) { unsigned long dwUID = unifiedStore2_InOut.GetUID(); const STORE& store_In = unifiedStore2_InOut.GetStore(); STORE store_Out; memset(&store_Out, 0, sizeof(STORE)); RebalanceLib::CItemArrayChecker< ContainerConstant::DEPOSIT_WIDTH, ContainerConstant::DEPOSIT_HEIGHT, ContainerConstant::MAX_DEPOSIT_TAB> depositChecker(TakeType::TS_DEPOSIT); depositChecker.FillTab(0); depositChecker.FillTab(1); RemoveItemFromContainer(dwUID, 0, &depositChecker, "UNIFIED_STORE_02", store_In.Data, store_In.dwSize, store_Out.Data, store_Out.dwSize); GiveItemToContainer(dwUID, 0, depositChecker, "UnifiedStore2", store_Out.Data, store_Out.dwSize, STORE::MAX_STORE_SIZE); unifiedStore2_InOut.SetStore(store_Out); return CONVERT_SUCCEEDED; } bool CGiveEventReward::LoadScript(const char* szScriptFileName) { /* # ÆÄÀÏ Çü½Ä - ÁÖ¼®ÀÔ´Ï´Ù. REMOVE:Áö¿ï¾ÆÀÌÅÛID:Key GIVE:Key:ÁÙ ¾ÆÀÌÅÛID:°³¼ö GIVE:Key:ÁÙ ¾ÆÀÌÅÛID:°³¼ö GIVE:Key:ÁÙ ¾ÆÀÌÅÛID:°³¼ö ... */ FILE* lpFile = fopen(szScriptFileName, "rt"); if (0 != lpFile) { const int MAX_BUFFER = 1024; char szBuffer[MAX_BUFFER]; const char* szDelimiter = "\r\n\t: "; while(fgets(szBuffer, MAX_BUFFER - 1, lpFile)) { // ÇÑ ¶óÀξ¿ Àоîµé¿© ÆÄ½ÌÀ» ÇÑ´Ù. char* szType = strtok(szBuffer, szDelimiter); if(0 != szType && '#' != szType[0]) { strupr(szType); if (0 == strcmp(szType, "REMOVE")) { char* szRemoveItem = strtok(0, szDelimiter); char* szGiveItemKey = strtok(0, szDelimiter); if (0 != szRemoveItem && 0 != szGiveItemKey) { m_EventItemList.push_back( EventItem(atoi(szRemoveItem), atoi(szGiveItemKey))); } } else if (0 == strcmp(szType, "GIVE")) { char* szGiveItemKey = strtok(0, szDelimiter); char* szGiveItem = strtok(0, szDelimiter); char* szGiveItemNum = strtok(0, szDelimiter); if (0 != szGiveItemKey && 0 != szGiveItem && 0 != szGiveItemNum) { GiveItem giveItem; const Item::ItemInfo* lpItemInfo = m_newItemMgr.GetItemInfo(atoi(szGiveItem)); if (0 != lpItemInfo) { // ½ÇÁ¦·Î ÀÖ´Â ¾ÆÀÌÅÛ¸¸ Áö±Þ ´ë»óÀ¸·Î ÇÑ´Ù. giveItem.first = atoi(szGiveItemKey); giveItem.second.first = lpItemInfo; giveItem.second.second = atoi(szGiveItemNum); m_GiveItemList.push_back(giveItem); } } } } } std::sort(m_EventItemList.begin(), m_EventItemList.end()); std::sort(m_GiveItemList.begin(), m_GiveItemList.end()); fclose(lpFile); return true; } return false; } struct CheckFirstOnly { bool operator () ( const CGiveEventReward::EventItem& lhs, const CGiveEventReward::EventItem& rhs) { return lhs.first < rhs.first; } bool operator () ( const CGiveEventReward::GiveItem& lhs, const CGiveEventReward::GiveItem& rhs) { return lhs.first < rhs.first; } }; // µ¥ÀÌÅÍ¿¡¼­ ¾ÆÀÌÅÛÀ» Á¦°ÅÇϰí Ä«¿îÆÃÇÑ´Ù. void CGiveEventReward::RemoveItemFromContainer(unsigned long dwUID, unsigned long dwCID, RebalanceLib::CItemChecker* lpItemChecker, const char* szPosition, const char* szData_In, unsigned long dwDataSize_In, char* szData_Out, unsigned long& dwDataSize_Out) { const char* szDataPos = szData_In; const char* szDataEnd = szData_In + dwDataSize_In; char* szDataPos_Out = szData_Out; EventItemList::iterator pos; EventItemList::iterator end = m_EventItemList.end(); std::pair give_range; GiveItem giveItem; // ¾ÆÀÌÅÛÀ» ÀüºÎ ¼øÈ¸Çϸç, ÄÁÅ×À̳ʸ¦ ä¿î´Ù. ¸¸ÀÏ ¾ÆÀÌÅÛÀÌ ´ë»ó ¾ÆÀÌÅÛÀ̸é ä¿ìÁö ¾Ê´Â´Ù. for (; szDataPos + sizeof(Item::ItemData) <= szDataEnd; ) { const Item::ItemData* lpItemData = reinterpret_cast(szDataPos); const Item::ItemInfo* lpItemInfo = m_newItemMgr.GetItemInfo(lpItemData->m_usProtoTypeID); if (0 == lpItemInfo) { ERRLOG6(g_Log, "UID:%10u / CID:%10u / ItemUID:%016I64X / PrototypeID:%6u / Num:%d / %s / " "½ºÅ©¸³Æ®¿¡ ¾ø´Â ¾ÆÀÌÅÛÀ̾ Á¦°ÅÇÕ´Ï´Ù.", dwUID, dwCID, lpItemData->m_dwUID, lpItemData->m_usProtoTypeID, lpItemData->m_cNumOrDurability, szPosition); } else { pos = std::lower_bound(m_EventItemList.begin(), end, EventItem(lpItemData->m_usProtoTypeID, 0), CheckFirstOnly()); if (pos != end && pos->first == lpItemData->m_usProtoTypeID) { // ¾ÆÀÌÅÛÀÌ ÀÖ´Ù. Ä«¿îÆÃÇÏ°í º¹»çÇÏÁö ¾ÊÀ½ giveItem.first = pos->second; // ÁÙ ¾ÆÀÌÅÛ Key giveItem.second.first = 0; giveItem.second.second = 0; give_range = std::equal_range(m_GiveItemList.begin(), m_GiveItemList.end(), giveItem, CheckFirstOnly()); for(; give_range.first != give_range.second; ++give_range.first) { for(int nCount = 0; nCount < lpItemData->m_cNumOrDurability; ++nCount) { if (0 != dwUID) { m_UIDGiveItemMap.insert(GiveItemMap::value_type(dwUID, *give_range.first)); } else if(0 != dwCID) { m_CIDGiveItemMap.insert(GiveItemMap::value_type(dwCID, *give_range.first)); } } } INFLOG5(g_Log, "UID:%10u / CID:%10u / PrototypeID:%6u / Num:%d / %s / " "¾ÆÀÌÅÛÀ» Áö±ÞÇϱâ À§ÇØ ÄÁÅ×À̳ʿ¡¼­ Á¦°ÅÇÕ´Ï´Ù", dwUID, dwCID, lpItemData->m_usProtoTypeID, lpItemData->m_cNumOrDurability, szPosition); } else { // ¾ÆÀÌÅÛÀÌ ¾ø´Ù. üĿ¿¡ ¼¼ÆÃÇÏ°í ±×³É º¹»çÇÑ´Ù. if (0 != lpItemChecker) { // ¾ÆÀÌÅÛ Ã¼Ä¿°¡ ÀÖÀ¸¸é À§Ä¡ ¹Ì¸® »ðÀÔ lpItemChecker->Set(lpItemData->m_ItemPos, lpItemInfo->m_DetailData.m_cXSize, lpItemInfo->m_DetailData.m_cYSize); } // µ¥ÀÌÅ͸¦ º¹»çÇÑ´Ù. memcpy(szDataPos_Out, lpItemData, lpItemData->m_cItemSize); szDataPos_Out += lpItemData->m_cItemSize; } } szDataPos += lpItemData->m_cItemSize; } dwDataSize_Out = static_cast(szDataPos_Out - szData_Out); } // ¾ÆÀÌÅÛÀ» ã¾Æ¼­ ³Ö¾î ÁØ´Ù. void CGiveEventReward::GiveItemToContainer(unsigned long dwUID, unsigned long dwCID, RebalanceLib::CItemChecker& itemChecker, const char* szPosition, char* szData_InOut, unsigned long& dwDataSize_InOut, unsigned long dwMaxDataSize, bool bLastChance) { unsigned long dwKey = 0; GiveItemMap* lpGiveItemMap = 0; if (0 != dwUID) { dwKey = dwUID; lpGiveItemMap = &m_UIDGiveItemMap; } else if (0 != dwCID) { dwKey = dwCID; lpGiveItemMap = &m_CIDGiveItemMap; } if (0 != dwKey && 0 != lpGiveItemMap) { std::pair find_range = lpGiveItemMap->equal_range(dwKey); for(; find_range.first != find_range.second; ) { // ÁÙ ¾ÆÀÌÅÛÀ» È®º¸Çß´Ù. const Item::ItemInfo* lpItemInfo = find_range.first->second.second.first; unsigned char cItemNum = find_range.first->second.second.second; // Âɰ³¼­ ³Ö´Â´Ù´øÁö ÇÏ´Â °Ç ÄÚµå·Î´Â Áö¿øÇÏÁö ¾Ê´Â´Ù. (½ºÅ©¸³Æ®¿¡¼­ Á¦¾î°¡´É) Item::ItemPos emptyPos; if (dwDataSize_InOut + sizeof(Item::ItemData) <= dwMaxDataSize && itemChecker.FindEmptyPos(emptyPos, lpItemInfo->m_DetailData.m_cXSize, lpItemInfo->m_DetailData.m_cYSize)) { Item::ItemData* lpItemData = reinterpret_cast(szData_InOut + dwDataSize_InOut); lpItemData->m_dwUID = m_DBItemSerialMgr.GetNewItemSerial(); lpItemData->m_usProtoTypeID = lpItemInfo->m_usProtoTypeID; lpItemData->m_ItemPos = emptyPos; lpItemData->m_cItemSize = sizeof(Item::ItemData); lpItemData->m_cNumOrDurability = cItemNum; dwDataSize_InOut += sizeof(Item::ItemData); itemChecker.Set(emptyPos, lpItemInfo->m_DetailData.m_cXSize, lpItemInfo->m_DetailData.m_cYSize); // ¾ÆÀÌÅÛÀ» ³Ö¾úÀ¸´Ï, Á¦°ÅÇÑ´Ù. find_range.first = lpGiveItemMap->erase(find_range.first); INFLOG7(g_Log, "UID:%10u / CID:%10u / PrototypeID:%6u / Num:%d / %s / Pos:%d / Index:0x%04X / " "¾ÆÀÌÅÛÀ» Áö±ÞÇß½À´Ï´Ù.", dwUID, dwCID, lpItemInfo->m_usProtoTypeID, cItemNum, szPosition, emptyPos.m_cPos, emptyPos.m_cIndex); } else { if(bLastChance) { // µ¥ÀÌÅ͸¦ ´õ ³ÖÀ» ¼ö ¾ø½À´Ï´Ù. ERRLOG5(g_Log, "UID:%10u / CID:%10u / PrototypeID:%6u / Num:%d / %s / " "µ¥ÀÌÅͰ¡ ²Ë á°Å³ª, ºó °ø°£ÀÌ ¾ø¾î¼­ ¾ÆÀÌÅÛÀ» ´õ ³ÖÀ» ¼ö ¾ø½À´Ï´Ù", dwUID, dwCID, lpItemInfo->m_usProtoTypeID, cItemNum, szPosition); } // ¾ÆÀÌÅÛÀ» ³ÖÀ» ¼ö ¾øÀ¸¹Ç·Î ±×³É ÁøÇà. ++find_range.first; } } } }