fix db cpp encoding

This commit is contained in:
sdgmt2 2024-04-01 14:20:00 +02:00
parent d471d99a24
commit dd74eafc24
No known key found for this signature in database
19 changed files with 490 additions and 488 deletions

View File

@ -135,7 +135,7 @@ void AuctionManager::LoadAuctionItem()
} }
int rows; int rows;
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음 if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
{ {
return; return;
} }
@ -182,7 +182,7 @@ void AuctionManager::LoadAuctionInfo()
} }
int rows; int rows;
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음 if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
{ {
return; return;
} }
@ -226,7 +226,7 @@ void AuctionManager::LoadSaleInfo()
} }
int rows; int rows;
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음 if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
{ {
return; return;
} }
@ -269,7 +269,7 @@ void AuctionManager::LoadWishInfo()
} }
int rows; int rows;
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음 if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
{ {
return; return;
} }
@ -311,7 +311,7 @@ void AuctionManager::LoadMyBidInfo ()
} }
int rows; int rows;
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음 if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
{ {
return; return;
} }
@ -518,7 +518,7 @@ AuctionResult AuctionManager::Impur(DWORD purchaser_id, const char* purchaser_na
return AUCTION_EXPIRED; return AUCTION_EXPIRED;
} }
// 즉구 해버렸으므로, 경매는 끝났다. // 즉구 해버렸으므로, 경매는 끝났다.
item_info->expired_time = 0; item_info->expired_time = 0;
item_info->bidder_id = purchaser_id; item_info->bidder_id = purchaser_id;
item_info->set_bidder_name (purchaser_name); item_info->set_bidder_name (purchaser_name);

View File

@ -114,7 +114,7 @@ bool CBlockCountry::IsBlockedCountryIp(const char *user_ip)
st_addr.s_addr = in_address; st_addr.s_addr = in_address;
if (INADDR_NONE == in_address) if (INADDR_NONE == in_address)
#endif #endif
return true; // 아이피가 괴상하니 일단 블럭처리 return true; // 아이피가 괴상하니 일단 블럭처리
DO_ALL_BLOCK_IP(iter) DO_ALL_BLOCK_IP(iter)
{ {

View File

@ -29,12 +29,12 @@ CItemCache::~CItemCache()
{ {
} }
// 이거 이상한데... // 이거 이상한데...
// Delete를 했으면, Cache도 해제해야 하는것 아닌가??? // Delete를 했으면, Cache도 해제해야 하는것 아닌가???
// 근데 Cache를 해제하는 부분이 없어. // 근데 Cache를 해제하는 부분이 없어.
// 못 찾은 건가? // 못 찾은 건가?
// 이렇게 해놓으면, 계속 시간이 될 때마다 아이템을 계속 지워... // 이렇게 해놓으면, 계속 시간이 될 때마다 아이템을 계속 지워...
// 이미 사라진 아이템인데... 확인사살?????? // 이미 사라진 아이템인데... 확인사살??????
// fixme // fixme
// by rtsummit // by rtsummit
void CItemCache::Delete() void CItemCache::Delete()
@ -52,12 +52,12 @@ void CItemCache::Delete()
OnFlush(); OnFlush();
//m_bNeedQuery = false; //m_bNeedQuery = false;
//m_lastUpdateTime = time(0) - m_expireTime; // 바로 타임아웃 되도록 하자. //m_lastUpdateTime = time(0) - m_expireTime; // 바로 타임아웃 되도록 하자.
} }
void CItemCache::OnFlush() void CItemCache::OnFlush()
{ {
if (m_data.vnum == 0) // vnum이 0이면 삭제하라고 표시된 것이다. if (m_data.vnum == 0) // vnum이 0이면 삭제하라고 표시된 것이다.
{ {
char szQuery[QUERY_MAX_LEN]; char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery), "DELETE FROM item%s WHERE id=%u", GetTablePostfix(), m_data.id); snprintf(szQuery, sizeof(szQuery), "DELETE FROM item%s WHERE id=%u", GetTablePostfix(), m_data.id);
@ -186,7 +186,7 @@ CItemPriceListTableCache::CItemPriceListTableCache()
void CItemPriceListTableCache::UpdateList(const TItemPriceListTable* pUpdateList) void CItemPriceListTableCache::UpdateList(const TItemPriceListTable* pUpdateList)
{ {
// //
// 이미 캐싱된 아이템과 중복된 아이템을 찾고 중복되지 않는 이전 정보는 tmpvec 에 넣는다. // 이미 캐싱된 아이템과 중복된 아이템을 찾고 중복되지 않는 이전 정보는 tmpvec 에 넣는다.
// //
std::vector<TItemPriceInfo> tmpvec; std::vector<TItemPriceInfo> tmpvec;
@ -202,7 +202,7 @@ void CItemPriceListTableCache::UpdateList(const TItemPriceListTable* pUpdateList
} }
// //
// pUpdateList 를 m_data 에 복사하고 남은 공간을 tmpvec 의 앞에서 부터 남은 만큼 복사한다. // pUpdateList 를 m_data 에 복사하고 남은 공간을 tmpvec 의 앞에서 부터 남은 만큼 복사한다.
// //
if (pUpdateList->byCount > SHOP_PRICELIST_MAX_NUM) if (pUpdateList->byCount > SHOP_PRICELIST_MAX_NUM)
@ -215,7 +215,7 @@ void CItemPriceListTableCache::UpdateList(const TItemPriceListTable* pUpdateList
memcpy(m_data.aPriceInfo, pUpdateList->aPriceInfo, sizeof(TItemPriceInfo) * pUpdateList->byCount); memcpy(m_data.aPriceInfo, pUpdateList->aPriceInfo, sizeof(TItemPriceInfo) * pUpdateList->byCount);
int nDeletedNum; // 삭제된 가격정보의 갯수 int nDeletedNum; // 삭제된 가격정보의 갯수
if (pUpdateList->byCount < SHOP_PRICELIST_MAX_NUM) if (pUpdateList->byCount < SHOP_PRICELIST_MAX_NUM)
{ {
@ -244,14 +244,14 @@ void CItemPriceListTableCache::OnFlush()
char szQuery[QUERY_MAX_LEN]; char szQuery[QUERY_MAX_LEN];
// //
// 이 캐시의 소유자에 대한 기존에 DB 에 저장된 아이템 가격정보를 모두 삭제한다. // 이 캐시의 소유자에 대한 기존에 DB 에 저장된 아이템 가격정보를 모두 삭제한다.
// //
snprintf(szQuery, sizeof(szQuery), "DELETE FROM myshop_pricelist%s WHERE owner_id = %u", GetTablePostfix(), m_data.dwOwnerID); snprintf(szQuery, sizeof(szQuery), "DELETE FROM myshop_pricelist%s WHERE owner_id = %u", GetTablePostfix(), m_data.dwOwnerID);
CDBManager::instance().ReturnQuery(szQuery, QID_ITEMPRICE_DESTROY, 0, NULL); CDBManager::instance().ReturnQuery(szQuery, QID_ITEMPRICE_DESTROY, 0, NULL);
// //
// 캐시의 내용을 모두 DB 에 쓴다. // 캐시의 내용을 모두 DB 에 쓴다.
// //
for (int idx = 0; idx < m_data.byCount; ++idx) for (int idx = 0; idx < m_data.byCount; ++idx)

View File

@ -248,7 +248,7 @@ bool CClientManager::Initialize()
LoadEventFlag(); LoadEventFlag();
// database character-set을 강제로 맞춤 // database character-set을 강제로 맞춤
if (g_stLocale == "big5" || g_stLocale == "sjis") if (g_stLocale == "big5" || g_stLocale == "sjis")
CDBManager::instance().QueryLocaleSet(); CDBManager::instance().QueryLocaleSet();
@ -261,7 +261,7 @@ void CClientManager::MainLoop()
SPDLOG_DEBUG("ClientManager pointer is {}", (void*) this); SPDLOG_DEBUG("ClientManager pointer is {}", (void*) this);
// 메인루프 // 메인루프
while (!m_bShutdowned) while (!m_bShutdowned)
{ {
while ((tmp = CDBManager::instance().PopResult())) while ((tmp = CDBManager::instance().PopResult()))
@ -275,7 +275,7 @@ void CClientManager::MainLoop()
} }
// //
// 메인루프 종료처리 // 메인루프 종료처리
// //
SPDLOG_DEBUG("MainLoop exited, Starting cache flushing"); SPDLOG_DEBUG("MainLoop exited, Starting cache flushing");
@ -283,7 +283,7 @@ void CClientManager::MainLoop()
itertype(m_map_playerCache) it = m_map_playerCache.begin(); itertype(m_map_playerCache) it = m_map_playerCache.begin();
//플레이어 테이블 캐쉬 플러쉬 //플레이어 테이블 캐쉬 플러쉬
while (it != m_map_playerCache.end()) while (it != m_map_playerCache.end())
{ {
CPlayerTableCache * c = (it++)->second; CPlayerTableCache * c = (it++)->second;
@ -295,7 +295,7 @@ void CClientManager::MainLoop()
itertype(m_map_itemCache) it2 = m_map_itemCache.begin(); itertype(m_map_itemCache) it2 = m_map_itemCache.begin();
//아이템 플러쉬 //아이템 플러쉬
while (it2 != m_map_itemCache.end()) while (it2 != m_map_itemCache.end())
{ {
CItemCache * c = (it2++)->second; CItemCache * c = (it2++)->second;
@ -307,7 +307,7 @@ void CClientManager::MainLoop()
// MYSHOP_PRICE_LIST // MYSHOP_PRICE_LIST
// //
// 개인상점 아이템 가격 리스트 Flush // 개인상점 아이템 가격 리스트 Flush
// //
for (itertype(m_mapItemPriceListCache) itPriceList = m_mapItemPriceListCache.begin(); itPriceList != m_mapItemPriceListCache.end(); ++itPriceList) for (itertype(m_mapItemPriceListCache) itPriceList = m_mapItemPriceListCache.begin(); itPriceList != m_mapItemPriceListCache.end(); ++itPriceList)
{ {
@ -327,7 +327,7 @@ void CClientManager::Quit()
void CClientManager::QUERY_BOOT(CPeer* peer, TPacketGDBoot * p) void CClientManager::QUERY_BOOT(CPeer* peer, TPacketGDBoot * p)
{ {
const BYTE bPacketVersion = 6; // BOOT 패킷이 바뀔때마다 번호를 올리도록 한다. const BYTE bPacketVersion = 6; // BOOT 패킷이 바뀔때마다 번호를 올리도록 한다.
std::vector<tAdminInfo> vAdmin; std::vector<tAdminInfo> vAdmin;
std::vector<std::string> vHost; std::vector<std::string> vHost;
@ -584,9 +584,9 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
ClientHandleInfo * pi = (ClientHandleInfo *) qi->pvData; ClientHandleInfo * pi = (ClientHandleInfo *) qi->pvData;
DWORD dwHandle = pi->dwHandle; DWORD dwHandle = pi->dwHandle;
// 여기에서 사용하는 account_index는 쿼리 순서를 말한다. // 여기에서 사용하는 account_index는 쿼리 순서를 말한다.
// 첫번째 패스워드 알아내기 위해 하는 쿼리가 0 // 첫번째 패스워드 알아내기 위해 하는 쿼리가 0
// 두번째 실제 데이터를 얻어놓는 쿼리가 1 // 두번째 실제 데이터를 얻어놓는 쿼리가 1
if (pi->account_index == 0) if (pi->account_index == 0)
{ {
@ -611,7 +611,7 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
{ {
MYSQL_ROW row = mysql_fetch_row(res->pSQLResult); MYSQL_ROW row = mysql_fetch_row(res->pSQLResult);
// 비밀번호가 틀리면.. // 비밀번호가 틀리면..
if (((!row[2] || !*row[2]) && strcmp("000000", szSafeboxPassword)) || if (((!row[2] || !*row[2]) && strcmp("000000", szSafeboxPassword)) ||
((row[2] && *row[2]) && strcmp(row[2], szSafeboxPassword))) ((row[2] && *row[2]) && strcmp(row[2], szSafeboxPassword)))
{ {
@ -677,8 +677,8 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
} }
// 쿼리에 에러가 있었으므로 응답할 경우 창고가 비어있는 것 처럼 // 쿼리에 에러가 있었으므로 응답할 경우 창고가 비어있는 것 처럼
// 보이기 때문에 창고가 아얘 안열리는게 나음 // 보이기 때문에 창고가 아얘 안열리는게 나음
if (!msg->Get()->pSQLResult) if (!msg->Get()->pSQLResult)
{ {
SPDLOG_ERROR("null safebox result"); SPDLOG_ERROR("null safebox result");
@ -787,8 +787,8 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
{ {
case 72723: case 72724: case 72725: case 72726: case 72723: case 72724: case 72725: case 72726:
case 72727: case 72728: case 72729: case 72730: case 72727: case 72728: case 72729: case 72730:
// 무시무시하지만 이전에 하던 걸 고치기는 무섭고... // 무시무시하지만 이전에 하던 걸 고치기는 무섭고...
// 그래서 그냥 하드 코딩. 선물 상자용 자동물약 아이템들. // 그래서 그냥 하드 코딩. 선물 상자용 자동물약 아이템들.
case 76004: case 76005: case 76021: case 76022: case 76004: case 76005: case 76021: case 76022:
case 79012: case 79013: case 79012: case 79013:
if (pItemAward->dwSocket2 == 0) if (pItemAward->dwSocket2 == 0)
@ -900,7 +900,7 @@ void CClientManager::RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg)
void CClientManager::QUERY_SAFEBOX_CHANGE_SIZE(CPeer * pkPeer, DWORD dwHandle, TSafeboxChangeSizePacket * p) void CClientManager::QUERY_SAFEBOX_CHANGE_SIZE(CPeer * pkPeer, DWORD dwHandle, TSafeboxChangeSizePacket * p)
{ {
ClientHandleInfo * pi = new ClientHandleInfo(dwHandle); ClientHandleInfo * pi = new ClientHandleInfo(dwHandle);
pi->account_index = p->bSize; // account_index를 사이즈로 임시로 사용 pi->account_index = p->bSize; // account_index를 사이즈로 임시로 사용
char szQuery[QUERY_MAX_LEN]; char szQuery[QUERY_MAX_LEN];
@ -988,7 +988,7 @@ void CClientManager::RESULT_PRICELIST_LOAD(CPeer* peer, SQLMsg* pMsg)
TItemPricelistReqInfo* pReqInfo = (TItemPricelistReqInfo*)static_cast<CQueryInfo*>(pMsg->pvUserData)->pvData; TItemPricelistReqInfo* pReqInfo = (TItemPricelistReqInfo*)static_cast<CQueryInfo*>(pMsg->pvUserData)->pvData;
// //
// DB 에서 로드한 정보를 Cache 에 저장 // DB 에서 로드한 정보를 Cache 에 저장
// //
TItemPriceListTable table; TItemPriceListTable table;
@ -1007,7 +1007,7 @@ void CClientManager::RESULT_PRICELIST_LOAD(CPeer* peer, SQLMsg* pMsg)
PutItemPriceListCache(&table); PutItemPriceListCache(&table);
// //
// 로드한 데이터를 Game server 에 전송 // 로드한 데이터를 Game server 에 전송
// //
TPacketMyshopPricelistHeader header; TPacketMyshopPricelistHeader header;
@ -1031,7 +1031,7 @@ void CClientManager::RESULT_PRICELIST_LOAD_FOR_UPDATE(SQLMsg* pMsg)
TItemPriceListTable* pUpdateTable = (TItemPriceListTable*)static_cast<CQueryInfo*>(pMsg->pvUserData)->pvData; TItemPriceListTable* pUpdateTable = (TItemPriceListTable*)static_cast<CQueryInfo*>(pMsg->pvUserData)->pvData;
// //
// DB 에서 로드한 정보를 Cache 에 저장 // DB 에서 로드한 정보를 Cache 에 저장
// //
TItemPriceListTable table; TItemPriceListTable table;
@ -1093,18 +1093,18 @@ void CClientManager::QUERY_EMPIRE_SELECT(CPeer * pkPeer, DWORD dwHandle, TEmpire
UINT g_start_map[4] = UINT g_start_map[4] =
{ {
0, // reserved 0, // reserved
1, // 신수국 1, // 신수국
21, // 천조국 21, // 천조국
41 // 진노국 41 // 진노국
}; };
// FIXME share with game // FIXME share with game
DWORD g_start_position[4][2]= DWORD g_start_position[4][2]=
{ {
{ 0, 0 }, { 0, 0 },
{ 469300, 964200 }, // 신수국 { 469300, 964200 }, // 신수국
{ 55700, 157900 }, // 천조국 { 55700, 157900 }, // 천조국
{ 969600, 278400 } // 진노국 { 969600, 278400 } // 진노국
}; };
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
@ -1155,7 +1155,7 @@ void CClientManager::QUERY_SETUP(CPeer * peer, DWORD dwHandle, const char * c_pD
peer->SetMaps(p->alMaps); peer->SetMaps(p->alMaps);
// //
// 어떤 맵이 어떤 서버에 있는지 보내기 // 어떤 맵이 어떤 서버에 있는지 보내기
// //
TMapLocation kMapLocations; TMapLocation kMapLocations;
@ -1262,7 +1262,7 @@ void CClientManager::QUERY_SETUP(CPeer * peer, DWORD dwHandle, const char * c_pD
peer->Encode(&vec_kMapLocations[0], sizeof(TMapLocation) * vec_kMapLocations.size()); peer->Encode(&vec_kMapLocations[0], sizeof(TMapLocation) * vec_kMapLocations.size());
// //
// 셋업 : 접속한 피어에 다른 피어들이 접속하게 만든다. (P2P 컨넥션 생성) // 셋업 : 접속한 피어에 다른 피어들이 접속하게 만든다. (P2P 컨넥션 생성)
// //
SPDLOG_DEBUG("SETUP: channel {} listen {} p2p {} count {}", peer->GetChannel(), p->wListenPort, p->wP2PPort, bMapCount); SPDLOG_DEBUG("SETUP: channel {} listen {} p2p {} count {}", peer->GetChannel(), p->wListenPort, p->wP2PPort, bMapCount);
@ -1278,7 +1278,7 @@ void CClientManager::QUERY_SETUP(CPeer * peer, DWORD dwHandle, const char * c_pD
if (tmp == peer) if (tmp == peer)
continue; continue;
// 채널이 0이라면 아직 SETUP 패킷이 오지 않은 피어 또는 auth라고 간주할 수 있음 // 채널이 0이라면 아직 SETUP 패킷이 오지 않은 피어 또는 auth라고 간주할 수 있음
if (0 == tmp->GetChannel()) if (0 == tmp->GetChannel())
continue; continue;
@ -1287,7 +1287,7 @@ void CClientManager::QUERY_SETUP(CPeer * peer, DWORD dwHandle, const char * c_pD
} }
// //
// 로그인 및 빌링정보 보내기 // 로그인 및 빌링정보 보내기
// //
TPacketLoginOnSetup * pck = (TPacketLoginOnSetup *) c_pData;; TPacketLoginOnSetup * pck = (TPacketLoginOnSetup *) c_pData;;
std::vector<TPacketBillingRepair> vec_repair; std::vector<TPacketBillingRepair> vec_repair;
@ -1359,8 +1359,8 @@ void CClientManager::QUERY_ITEM_SAVE(CPeer * pkPeer, const char * c_pData)
{ {
TPlayerItem * p = (TPlayerItem *) c_pData; TPlayerItem * p = (TPlayerItem *) c_pData;
// 창고면 캐쉬하지 않고, 캐쉬에 있던 것도 빼버려야 한다. // 창고면 캐쉬하지 않고, 캐쉬에 있던 것도 빼버려야 한다.
// auction은 이 루트를 타지 않아야 한다. EnrollInAuction을 타야한다. // auction은 이 루트를 타지 않아야 한다. EnrollInAuction을 타야한다.
if (p->window == SAFEBOX || p->window == MALL) if (p->window == SAFEBOX || p->window == MALL)
{ {
@ -1495,7 +1495,7 @@ void CClientManager::PutItemCache(TPlayerItem * pNew, bool bSkipQuery)
c = GetItemCache(pNew->id); c = GetItemCache(pNew->id);
// 아이템 새로 생성 // 아이템 새로 생성
if (!c) if (!c)
{ {
SPDLOG_TRACE("ITEM_CACHE: PutItemCache ==> New CItemCache id{} vnum{} new owner{}", pNew->id, pNew->vnum, pNew->owner); SPDLOG_TRACE("ITEM_CACHE: PutItemCache ==> New CItemCache id{} vnum{} new owner{}", pNew->id, pNew->vnum, pNew->owner);
@ -1503,15 +1503,15 @@ void CClientManager::PutItemCache(TPlayerItem * pNew, bool bSkipQuery)
c = new CItemCache; c = new CItemCache;
m_map_itemCache.insert(TItemCacheMap::value_type(pNew->id, c)); m_map_itemCache.insert(TItemCacheMap::value_type(pNew->id, c));
} }
// 있을시 // 있을시
else else
{ {
SPDLOG_TRACE("ITEM_CACHE: PutItemCache ==> Have Cache"); SPDLOG_TRACE("ITEM_CACHE: PutItemCache ==> Have Cache");
// 소유자가 틀리면 // 소유자가 틀리면
if (pNew->owner != c->Get()->owner) if (pNew->owner != c->Get()->owner)
{ {
// 이미 이 아이템을 가지고 있었던 유저로 부터 아이템을 삭제한다. // 이미 이 아이템을 가지고 있었던 유저로 부터 아이템을 삭제한다.
TItemCacheSetPtrMap::iterator it = m_map_pkItemCacheSetPtr.find(c->Get()->owner); TItemCacheSetPtrMap::iterator it = m_map_pkItemCacheSetPtr.find(c->Get()->owner);
if (it != m_map_pkItemCacheSetPtr.end()) if (it != m_map_pkItemCacheSetPtr.end())
@ -1522,7 +1522,7 @@ void CClientManager::PutItemCache(TPlayerItem * pNew, bool bSkipQuery)
} }
} }
// 새로운 정보 업데이트 // 새로운 정보 업데이트
c->Put(pNew, bSkipQuery); c->Put(pNew, bSkipQuery);
TItemCacheSetPtrMap::iterator it = m_map_pkItemCacheSetPtr.find(c->Get()->owner); TItemCacheSetPtrMap::iterator it = m_map_pkItemCacheSetPtr.find(c->Get()->owner);
@ -1534,8 +1534,8 @@ void CClientManager::PutItemCache(TPlayerItem * pNew, bool bSkipQuery)
} }
else else
{ {
// 현재 소유자가 없으므로 바로 저장해야 다음 접속이 올 때 SQL에 쿼리하여 // 현재 소유자가 없으므로 바로 저장해야 다음 접속이 올 때 SQL에 쿼리하여
// 받을 수 있으므로 바로 저장한다. // 받을 수 있으므로 바로 저장한다.
SPDLOG_TRACE("ITEM_CACHE: direct save {} id {}", c->Get()->owner, c->Get()->id); SPDLOG_TRACE("ITEM_CACHE: direct save {} id {}", c->Get()->owner, c->Get()->id);
c->OnFlush(); c->OnFlush();
@ -1591,7 +1591,7 @@ void CClientManager::UpdatePlayerCache()
c->Flush(); c->Flush();
// Item Cache도 업데이트 // Item Cache도 업데이트
UpdateItemCacheSet(c->Get()->id); UpdateItemCacheSet(c->Get()->id);
} }
else if (c->CheckFlushTimeout()) else if (c->CheckFlushTimeout())
@ -1617,7 +1617,7 @@ void CClientManager::UpdateItemCache()
{ {
CItemCache * c = (it++)->second; CItemCache * c = (it++)->second;
// 아이템은 Flush만 한다. // 아이템은 Flush만 한다.
if (c->CheckFlushTimeout()) if (c->CheckFlushTimeout())
{ {
SPDLOG_TRACE("UpdateItemCache ==> Flush() vnum {} id owner {}", c->Get()->vnum, c->Get()->id, c->Get()->owner); SPDLOG_TRACE("UpdateItemCache ==> Flush() vnum {} id owner {}", c->Get()->vnum, c->Get()->id, c->Get()->owner);
@ -1662,7 +1662,7 @@ void CClientManager::QUERY_ITEM_DESTROY(CPeer * pkPeer, const char * c_pData)
SPDLOG_TRACE("HEADER_GD_ITEM_DESTROY: PID {} ID {}", dwPID, dwID); SPDLOG_TRACE("HEADER_GD_ITEM_DESTROY: PID {} ID {}", dwPID, dwID);
if (dwPID == 0) // 아무도 가진 사람이 없었다면, 비동기 쿼리 if (dwPID == 0) // 아무도 가진 사람이 없었다면, 비동기 쿼리
CDBManager::instance().AsyncQuery(szQuery); CDBManager::instance().AsyncQuery(szQuery);
else else
CDBManager::instance().ReturnQuery(szQuery, QID_ITEM_DESTROY, pkPeer->GetHandle(), NULL); CDBManager::instance().ReturnQuery(szQuery, QID_ITEM_DESTROY, pkPeer->GetHandle(), NULL);
@ -1740,7 +1740,7 @@ void CClientManager::QUERY_RELOAD_PROTO()
// ADD_GUILD_PRIV_TIME // ADD_GUILD_PRIV_TIME
/** /**
* @version 05/06/08 Bang2ni - * @version 05/06/08 Bang2ni -
*/ */
void CClientManager::AddGuildPriv(TPacketGiveGuildPriv* p) void CClientManager::AddGuildPriv(TPacketGiveGuildPriv* p)
{ {
@ -2220,8 +2220,8 @@ void CClientManager::WeddingEnd(TPacketWeddingEnd * p)
} }
// //
// 캐시에 가격정보가 있으면 캐시를 업데이트 하고 캐시에 가격정보가 없다면 // 캐시에 가격정보가 있으면 캐시를 업데이트 하고 캐시에 가격정보가 없다면
// 우선 기존의 데이터를 로드한 뒤에 기존의 정보로 캐시를 만들고 새로 받은 가격정보를 업데이트 한다. // 우선 기존의 데이터를 로드한 뒤에 기존의 정보로 캐시를 만들고 새로 받은 가격정보를 업데이트 한다.
// //
void CClientManager::MyshopPricelistUpdate(const TPacketMyshopPricelistHeader* pPacket) void CClientManager::MyshopPricelistUpdate(const TPacketMyshopPricelistHeader* pPacket)
{ {
@ -2262,7 +2262,7 @@ void CClientManager::MyshopPricelistUpdate(const TPacketMyshopPricelistHeader* p
} }
// MYSHOP_PRICE_LIST // MYSHOP_PRICE_LIST
// 캐시된 가격정보가 있으면 캐시를 읽어 바로 전송하고 캐시에 정보가 없으면 DB 에 쿼리를 한다. // 캐시된 가격정보가 있으면 캐시를 읽어 바로 전송하고 캐시에 정보가 없으면 DB 에 쿼리를 한다.
// //
void CClientManager::MyshopPricelistRequest(CPeer* peer, DWORD dwHandle, DWORD dwPlayerID) void CClientManager::MyshopPricelistRequest(CPeer* peer, DWORD dwHandle, DWORD dwPlayerID)
{ {
@ -2655,15 +2655,15 @@ void CClientManager::ProcessPackets(CPeer * peer)
ComeToVote(peer, dwHandle, data); ComeToVote(peer, dwHandle, data);
break; break;
case HEADER_GD_RMCANDIDACY: //< 후보 제거 (운영자) case HEADER_GD_RMCANDIDACY: //< 후보 제거 (운영자)
RMCandidacy(peer, dwHandle, data); RMCandidacy(peer, dwHandle, data);
break; break;
case HEADER_GD_SETMONARCH: ///<군주설정 (운영자) case HEADER_GD_SETMONARCH: ///<군주설정 (운영자)
SetMonarch(peer, dwHandle, data); SetMonarch(peer, dwHandle, data);
break; break;
case HEADER_GD_RMMONARCH: ///<군주삭제 case HEADER_GD_RMMONARCH: ///<군주삭제
RMMonarch(peer, dwHandle, data); RMMonarch(peer, dwHandle, data);
break; break;
//END_MONARCH //END_MONARCH
@ -2864,9 +2864,9 @@ CPeer * CClientManager::GetAnyPeer()
return m_peerList.front(); return m_peerList.front();
} }
// DB 매니저로 부터 받은 결과를 처리한다. // DB 매니저로 부터 받은 결과를 처리한다.
// //
// @version 05/06/10 Bang2ni - 가격정보 관련 쿼리(QID_ITEMPRICE_XXX) 추가 // @version 05/06/10 Bang2ni - 가격정보 관련 쿼리(QID_ITEMPRICE_XXX) 추가
int CClientManager::AnalyzeQueryResult(SQLMsg * msg) int CClientManager::AnalyzeQueryResult(SQLMsg * msg)
{ {
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData; CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
@ -2984,7 +2984,7 @@ void UsageLog()
char *time_s; char *time_s;
struct tm lt; struct tm lt;
int avg = g_dwUsageAvg / 3600; // 60 초 * 60 분 int avg = g_dwUsageAvg / 3600; // 60 초 * 60 분
fp = fopen("usage.txt", "a+"); fp = fopen("usage.txt", "a+");
@ -3017,7 +3017,7 @@ int CClientManager::Process()
++thecore_heart->pulse; ++thecore_heart->pulse;
/* /*
//30분마다 변경 //30분마다 변경
if (((thecore_pulse() % (60 * 30 * 10)) == 0)) if (((thecore_pulse() % (60 * 30 * 10)) == 0))
{ {
g_iPlayerCacheFlushSeconds = std::max(60, rand() % 180); g_iPlayerCacheFlushSeconds = std::max(60, rand() % 180);
@ -3095,11 +3095,11 @@ int CClientManager::Process()
m_iCacheFlushCount = 0; m_iCacheFlushCount = 0;
//플레이어 플러쉬 //플레이어 플러쉬
UpdatePlayerCache(); UpdatePlayerCache();
//아이템 플러쉬 //아이템 플러쉬
UpdateItemCache(); UpdateItemCache();
//로그아웃시 처리- 캐쉬셋 플러쉬 //로그아웃시 처리- 캐쉬셋 플러쉬
UpdateLogoutPlayer(); UpdateLogoutPlayer();
// MYSHOP_PRICE_LIST // MYSHOP_PRICE_LIST
@ -3169,13 +3169,13 @@ int CClientManager::Process()
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
} }
if (!(thecore_heart->pulse % (thecore_heart->passes_per_sec * 60))) // 60초에 한번 if (!(thecore_heart->pulse % (thecore_heart->passes_per_sec * 60))) // 60초에 한번
{ {
// 유니크 아이템을 위한 시간을 보낸다. // 유니크 아이템을 위한 시간을 보낸다.
CClientManager::instance().SendTime(); CClientManager::instance().SendTime();
} }
if (!(thecore_heart->pulse % (thecore_heart->passes_per_sec * 3600))) // 한시간에 한번 if (!(thecore_heart->pulse % (thecore_heart->passes_per_sec * 3600))) // 한시간에 한번
{ {
CMoneyLog::instance().Save(); CMoneyLog::instance().Save();
} }
@ -3190,7 +3190,7 @@ int CClientManager::Process()
DWORD CClientManager::GetUserCount() DWORD CClientManager::GetUserCount()
{ {
// 단순히 로그인 카운트를 센다.. --; // 단순히 로그인 카운트를 센다.. --;
return m_map_kLogonAccount.size(); return m_map_kLogonAccount.size();
} }
@ -3250,7 +3250,7 @@ bool CClientManager::InitializeNowItemID()
{ {
DWORD dwMin, dwMax; DWORD dwMin, dwMax;
//아이템 ID를 초기화 한다. //아이템 ID를 초기화 한다.
if (!CConfig::instance().GetTwoValue("ITEM_ID_RANGE", &dwMin, &dwMax)) if (!CConfig::instance().GetTwoValue("ITEM_ID_RANGE", &dwMin, &dwMax))
{ {
SPDLOG_ERROR("conf.txt: Cannot find ITEM_ID_RANGE [start_item_id] [end_item_id]"); SPDLOG_ERROR("conf.txt: Cannot find ITEM_ID_RANGE [start_item_id] [end_item_id]");
@ -3680,7 +3680,7 @@ bool CClientManager::InitializeLocalization()
bool CClientManager::__GetAdminInfo(const char *szIP, std::vector<tAdminInfo> & rAdminVec) bool CClientManager::__GetAdminInfo(const char *szIP, std::vector<tAdminInfo> & rAdminVec)
{ {
//szIP == NULL 일경우 모든서버에 운영자 권한을 갖는다. //szIP == NULL 일경우 모든서버에 운영자 권한을 갖는다.
char szQuery[512]; char szQuery[512];
snprintf(szQuery, sizeof(szQuery), snprintf(szQuery, sizeof(szQuery),
"SELECT mID,mAccount,mName,mContactIP,mServerIP,mAuthority FROM gmlist WHERE mServerIP='ALL' or mServerIP='%s'", "SELECT mID,mAccount,mName,mContactIP,mServerIP,mAuthority FROM gmlist WHERE mServerIP='ALL' or mServerIP='%s'",
@ -4233,7 +4233,7 @@ void CClientManager::SendSpareItemIDRange(CPeer* peer)
} }
// //
// Login Key만 맵에서 지운다. // Login Key만 맵에서 지운다.
// //
void CClientManager::DeleteLoginKey(TPacketDC *data) void CClientManager::DeleteLoginKey(TPacketDC *data)
{ {
@ -4346,7 +4346,7 @@ void CClientManager::EnrollInAuction (CPeer * peer, DWORD owner_id, AuctionEnrol
SPDLOG_ERROR("Player id {} doesn't have item {}.", owner_id, data->get_item_id()); SPDLOG_ERROR("Player id {} doesn't have item {}.", owner_id, data->get_item_id());
return; return;
} }
// 현재 시각 + 24시간 후. // 현재 시각 + 24시간 후.
time_t expired_time = time(0) + 24 * 60 * 60; time_t expired_time = time(0) + 24 * 60 * 60;
TAuctionItemInfo auctioned_item_info (item->vnum, data->get_bid_price(), TAuctionItemInfo auctioned_item_info (item->vnum, data->get_bid_price(),
data->get_impur_price(), owner_id, "", expired_time, data->get_item_id(), 0, data->get_empire()); data->get_impur_price(), owner_id, "", expired_time, data->get_item_id(), 0, data->get_empire());
@ -4365,7 +4365,7 @@ void CClientManager::EnrollInAuction (CPeer * peer, DWORD owner_id, AuctionEnrol
} }
else else
{ {
// 아이템 케시를 Auction에 등록 했으니 ClientManager에서는 뺀다. // 아이템 케시를 Auction에 등록 했으니 ClientManager에서는 뺀다.
TItemCacheSetPtrMap::iterator it = m_map_pkItemCacheSetPtr.find(item->owner); TItemCacheSetPtrMap::iterator it = m_map_pkItemCacheSetPtr.find(item->owner);
if (it != m_map_pkItemCacheSetPtr.end()) if (it != m_map_pkItemCacheSetPtr.end())
@ -4418,7 +4418,7 @@ void CClientManager::EnrollInSale (CPeer * peer, DWORD owner_id, AuctionEnrollSa
SPDLOG_ERROR("Player id {} doesn't have item {}.", owner_id, data->get_item_id()); SPDLOG_ERROR("Player id {} doesn't have item {}.", owner_id, data->get_item_id());
return; return;
} }
// 현재 시각 + 24시간 후. // 현재 시각 + 24시간 후.
time_t expired_time = time(0) + 24 * 60 * 60; time_t expired_time = time(0) + 24 * 60 * 60;
TSaleItemInfo sold_item_info (item->vnum, data->get_sale_price(), TSaleItemInfo sold_item_info (item->vnum, data->get_sale_price(),
owner_id, player->name, data->get_item_id(), data->get_wisher_id()); owner_id, player->name, data->get_item_id(), data->get_wisher_id());
@ -4437,7 +4437,7 @@ void CClientManager::EnrollInSale (CPeer * peer, DWORD owner_id, AuctionEnrollSa
} }
else else
{ {
// 아이템 케시를 Auction에 등록 했으니 ClientManager에서는 뺀다. // 아이템 케시를 Auction에 등록 했으니 ClientManager에서는 뺀다.
TItemCacheSetPtrMap::iterator it = m_map_pkItemCacheSetPtr.find(item->owner); TItemCacheSetPtrMap::iterator it = m_map_pkItemCacheSetPtr.find(item->owner);
if (it != m_map_pkItemCacheSetPtr.end()) if (it != m_map_pkItemCacheSetPtr.end())
@ -4477,7 +4477,7 @@ void CClientManager::EnrollInWish (CPeer * peer, DWORD wisher_id, AuctionEnrollW
CPlayerTableCache* player_cache = it->second; CPlayerTableCache* player_cache = it->second;
TPlayerTable* player = player_cache->Get(false); TPlayerTable* player = player_cache->Get(false);
// 현재 시각 + 24시간 후. // 현재 시각 + 24시간 후.
time_t expired_time = time(0) + 24 * 60 * 60; time_t expired_time = time(0) + 24 * 60 * 60;
TWishItemInfo wished_item_info (data->get_item_num(), data->get_wish_price(), wisher_id, player->name, expired_time, data->get_empire()); TWishItemInfo wished_item_info (data->get_item_num(), data->get_wish_price(), wisher_id, player->name, expired_time, data->get_empire());
@ -4844,11 +4844,11 @@ void CClientManager::AuctionDeleteSaleItem (CPeer * peer, DWORD actor_id, DWORD
AuctionManager::instance().DeleteSaleItem (actor_id, item_id); AuctionManager::instance().DeleteSaleItem (actor_id, item_id);
} }
// ReBid는 이전 입찰금액에 더해서 입찰한다. // ReBid는 이전 입찰금액에 더해서 입찰한다.
// ReBid에선 data->bid_price가 이전 입찰가에 더해져서 // ReBid에선 data->bid_price가 이전 입찰가에 더해져서
// 그 금액으로 rebid하는 것. // 그 금액으로 rebid하는 것.
// 이렇게 한 이유는 rebid에 실패 했을 때, // 이렇게 한 이유는 rebid에 실패 했을 때,
// 유저의 호주머니에서 뺀 돈을 돌려주기 편하게 하기 위함이다. // 유저의 호주머니에서 뺀 돈을 돌려주기 편하게 하기 위함이다.
void CClientManager::AuctionReBid (CPeer * peer, DWORD bidder_id, AuctionBidInfo* data) void CClientManager::AuctionReBid (CPeer * peer, DWORD bidder_id, AuctionBidInfo* data)
{ {
@ -4873,14 +4873,14 @@ void CClientManager::AuctionReBid (CPeer * peer, DWORD bidder_id, AuctionBidInfo
{ {
SPDLOG_DEBUG("ReBid Success. bidder_id item_id {} {}", bidder_id, data->get_item_id()); SPDLOG_DEBUG("ReBid Success. bidder_id item_id {} {}", bidder_id, data->get_item_id());
} }
// 이건 FAIL이 떠서는 안돼. // 이건 FAIL이 떠서는 안돼.
// FAIL이 뜰 수가 없는게, MyBid에 있는 bidder_id에 대한 컨텐츠는 bidder_id만이 접근 할 수 있거든? // FAIL이 뜰 수가 없는게, MyBid에 있는 bidder_id에 대한 컨텐츠는 bidder_id만이 접근 할 수 있거든?
// 그러므로 다른 것이 다 정상적으로 작동한다고 가정 한다면 // 그러므로 다른 것이 다 정상적으로 작동한다고 가정 한다면
// 한 게임 서버 내에서 bidder_id로 MyBid를 수정한다 할 지라도, 그건 동기화 문제가 없어. // 한 게임 서버 내에서 bidder_id로 MyBid를 수정한다 할 지라도, 그건 동기화 문제가 없어.
// 다른 게임 서버에 똑같은 bidder_id를 가진 놈이 있을 수가 없으니까. // 다른 게임 서버에 똑같은 bidder_id를 가진 놈이 있을 수가 없으니까.
// 그러므로 그 게임 서버에서 BidCancel 명령을 db에 날렸다는 것은, // 그러므로 그 게임 서버에서 BidCancel 명령을 db에 날렸다는 것은,
// 이미 그 부분에 대해서는 검사가 완벽하다는 것이야. // 이미 그 부분에 대해서는 검사가 완벽하다는 것이야.
// 그래도 혹시나 싶어서, 디버깅을 위해 fail 코드를 남겨둔다. // 그래도 혹시나 싶어서, 디버깅을 위해 fail 코드를 남겨둔다.
if (result <= AUCTION_FAIL) if (result <= AUCTION_FAIL)
{ {
TPacketDGResultAuction enroll_result; TPacketDGResultAuction enroll_result;
@ -4915,14 +4915,14 @@ void CClientManager::AuctionBidCancel (CPeer * peer, DWORD bidder_id, DWORD item
{ {
AuctionResult result = AuctionManager::instance().BidCancel (bidder_id, item_id); AuctionResult result = AuctionManager::instance().BidCancel (bidder_id, item_id);
// 이건 FAIL이 떠서는 안돼. // 이건 FAIL이 떠서는 안돼.
// FAIL이 뜰 수가 없는게, MyBid에 있는 bidder_id에 대한 컨텐츠는 bidder_id만이 접근 할 수 있거든? // FAIL이 뜰 수가 없는게, MyBid에 있는 bidder_id에 대한 컨텐츠는 bidder_id만이 접근 할 수 있거든?
// 그러므로 다른 것이 다 정상적으로 작동한다고 가정 한다면 // 그러므로 다른 것이 다 정상적으로 작동한다고 가정 한다면
// 한 게임 서버 내에서 bidder_id로 MyBid를 수정한다 할 지라도, 그건 동기화 문제가 없어. // 한 게임 서버 내에서 bidder_id로 MyBid를 수정한다 할 지라도, 그건 동기화 문제가 없어.
// 다른 게임 서버에 똑같은 bidder_id를 가진 놈이 있을 수가 없으니까. // 다른 게임 서버에 똑같은 bidder_id를 가진 놈이 있을 수가 없으니까.
// 그러므로 그 게임 서버에서 BidCancel 명령을 db에 날렸다는 것은, // 그러므로 그 게임 서버에서 BidCancel 명령을 db에 날렸다는 것은,
// 이미 그 부분에 대해서는 검사가 완벽하다는 것이야. // 이미 그 부분에 대해서는 검사가 완벽하다는 것이야.
// 그래도 혹시나 싶어서, 디버깅을 위해 fail 코드를 남겨둔다. // 그래도 혹시나 싶어서, 디버깅을 위해 fail 코드를 남겨둔다.
if (result <= AUCTION_FAIL) if (result <= AUCTION_FAIL)
{ {
TPacketDGResultAuction enroll_result; TPacketDGResultAuction enroll_result;

View File

@ -171,42 +171,42 @@ class FCompareVnum
bool CClientManager::InitializeMobTable() bool CClientManager::InitializeMobTable()
{ {
//================== 함수 설명 ==================// //================== 함수 설명 ==================//
//1. 요약 : 'mob_proto.txt', 'mob_proto_test.txt', 'mob_names.txt' 파일을 읽고, //1. 요약 : 'mob_proto.txt', 'mob_proto_test.txt', 'mob_names.txt' 파일을 읽고,
// (!)[mob_table] 테이블 오브젝트를 생성한다. (타입 : TMobTable) // (!)[mob_table] 테이블 오브젝트를 생성한다. (타입 : TMobTable)
//2. 순서 //2. 순서
// 1) 'mob_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다. // 1) 'mob_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
// 2) 'mob_proto_test.txt'파일과 (a)[localMap] 맵으로 // 2) 'mob_proto_test.txt'파일과 (a)[localMap] 맵으로
// (b)[test_map_mobTableByVnum](vnum:TMobTable) 맵을 생성한다. // (b)[test_map_mobTableByVnum](vnum:TMobTable) 맵을 생성한다.
// 3) 'mob_proto.txt' 파일과 (a)[localMap] 맵으로 // 3) 'mob_proto.txt' 파일과 (a)[localMap] 맵으로
// (!)[mob_table] 테이블을 만든다. // (!)[mob_table] 테이블을 만든다.
// <참고> // <참고>
// 각 row 들 중, // 각 row 들 중,
// (b)[test_map_mobTableByVnum],(!)[mob_table] 모두에 있는 row는 // (b)[test_map_mobTableByVnum],(!)[mob_table] 모두에 있는 row는
// (b)[test_map_mobTableByVnum]의 것을 사용한다. // (b)[test_map_mobTableByVnum]의 것을 사용한다.
// 4) (b)[test_map_mobTableByVnum]의 row중, (!)[mob_table]에 없는 것을 추가한다. // 4) (b)[test_map_mobTableByVnum]의 row중, (!)[mob_table]에 없는 것을 추가한다.
//3. 테스트 //3. 테스트
// 1)'mob_proto.txt' 정보가 mob_table에 잘 들어갔는지. -> 완료 // 1)'mob_proto.txt' 정보가 mob_table에 잘 들어갔는지. -> 완료
// 2)'mob_names.txt' 정보가 mob_table에 잘 들어갔는지. // 2)'mob_names.txt' 정보가 mob_table에 잘 들어갔는지.
// 3)'mob_proto_test.txt' 에서 [겹치는] 정보가 mob_table 에 잘 들어갔는지. // 3)'mob_proto_test.txt' 에서 [겹치는] 정보가 mob_table 에 잘 들어갔는지.
// 4)'mob_proto_test.txt' 에서 [새로운] 정보가 mob_table 에 잘 들어갔는지. // 4)'mob_proto_test.txt' 에서 [새로운] 정보가 mob_table 에 잘 들어갔는지.
// 5) (최종) 게임 클라이언트에서 제대로 작동 하는지. // 5) (최종) 게임 클라이언트에서 제대로 작동 하는지.
//_______________________________________________// //_______________________________________________//
//===============================================// //===============================================//
// 1) 'mob_names.txt' 파일을 읽어서 (a)[localMap] 맵을 만든다. // 1) 'mob_names.txt' 파일을 읽어서 (a)[localMap] 맵을 만든다.
//<(a)localMap 맵 생성> //<(a)localMap 맵 생성>
map<int,const char*> localMap; map<int,const char*> localMap;
bool isNameFile = true; bool isNameFile = true;
//<파일 읽기> //<파일 읽기>
cCsvTable nameData; cCsvTable nameData;
if(!nameData.Load("mob_names.txt",'\t')) if(!nameData.Load("mob_names.txt",'\t'))
{ {
SPDLOG_ERROR("mob_names.txt 파일을 읽어오지 못했습니다"); SPDLOG_ERROR("mob_names.txt 파일을 읽어오지 못했습니다");
isNameFile = false; isNameFile = false;
} else { } else {
nameData.Next(); //설명row 생략. nameData.Next(); //설명row 생략.
while(nameData.Next()) { while(nameData.Next()) {
localMap[atoi(nameData.AsStringByIndex(0))] = nameData.AsStringByIndex(1); localMap[atoi(nameData.AsStringByIndex(0))] = nameData.AsStringByIndex(1);
} }
@ -215,35 +215,35 @@ bool CClientManager::InitializeMobTable()
//===============================================// //===============================================//
// 2) 'mob_proto_test.txt'파일과 (a)localMap 맵으로 // 2) 'mob_proto_test.txt'파일과 (a)localMap 맵으로
// (b)[test_map_mobTableByVnum](vnum:TMobTable) 맵을 생성한다. // (b)[test_map_mobTableByVnum](vnum:TMobTable) 맵을 생성한다.
//0. //0.
set<int> vnumSet; //테스트용 파일 데이터중, 신규여부 확인에 사용. set<int> vnumSet; //테스트용 파일 데이터중, 신규여부 확인에 사용.
//1. 파일 읽어오기 //1. 파일 읽어오기
bool isTestFile = true; bool isTestFile = true;
cCsvTable test_data; cCsvTable test_data;
if(!test_data.Load("mob_proto_test.txt",'\t')) if(!test_data.Load("mob_proto_test.txt",'\t'))
{ {
SPDLOG_ERROR("테스트 파일이 없습니다. 그대로 진행합니다."); SPDLOG_ERROR("테스트 파일이 없습니다. 그대로 진행합니다.");
isTestFile = false; isTestFile = false;
} }
//2. (c)[test_map_mobTableByVnum](vnum:TMobTable) 맵 생성. //2. (c)[test_map_mobTableByVnum](vnum:TMobTable) 맵 생성.
map<DWORD, TMobTable *> test_map_mobTableByVnum; map<DWORD, TMobTable *> test_map_mobTableByVnum;
if (isTestFile) { if (isTestFile) {
test_data.Next(); //설명 로우 넘어가기. test_data.Next(); //설명 로우 넘어가기.
//ㄱ. 테스트 몬스터 테이블 생성. //ㄱ. 테스트 몬스터 테이블 생성.
TMobTable * test_mob_table = NULL; TMobTable * test_mob_table = NULL;
int test_MobTableSize = test_data.m_File.GetRowCount()-1; int test_MobTableSize = test_data.m_File.GetRowCount()-1;
test_mob_table = new TMobTable[test_MobTableSize]; test_mob_table = new TMobTable[test_MobTableSize];
memset(test_mob_table, 0, sizeof(TMobTable) * test_MobTableSize); memset(test_mob_table, 0, sizeof(TMobTable) * test_MobTableSize);
//ㄴ. 테스트 몬스터 테이블에 값을 넣고, 맵에까지 넣기. //ㄴ. 테스트 몬스터 테이블에 값을 넣고, 맵에까지 넣기.
while(test_data.Next()) { while(test_data.Next()) {
if (!Set_Proto_Mob_Table(test_mob_table, test_data, localMap)) if (!Set_Proto_Mob_Table(test_mob_table, test_data, localMap))
{ {
SPDLOG_ERROR("몹 프로토 테이블 셋팅 실패."); SPDLOG_ERROR("몹 프로토 테이블 셋팅 실패.");
} }
test_map_mobTableByVnum.insert(std::map<DWORD, TMobTable *>::value_type(test_mob_table->dwVnum, test_mob_table)); test_map_mobTableByVnum.insert(std::map<DWORD, TMobTable *>::value_type(test_mob_table->dwVnum, test_mob_table));
@ -254,22 +254,22 @@ bool CClientManager::InitializeMobTable()
} }
// 3) 'mob_proto.txt' 파일과 (a)[localMap] 맵으로 // 3) 'mob_proto.txt' 파일과 (a)[localMap] 맵으로
// (!)[mob_table] 테이블을 만든다. // (!)[mob_table] 테이블을 만든다.
// <참고> // <참고>
// 각 row 들 중, // 각 row 들 중,
// (b)[test_map_mobTableByVnum],(!)[mob_table] 모두에 있는 row는 // (b)[test_map_mobTableByVnum],(!)[mob_table] 모두에 있는 row는
// (b)[test_map_mobTableByVnum]의 것을 사용한다. // (b)[test_map_mobTableByVnum]의 것을 사용한다.
//1. 파일 읽기. //1. 파일 읽기.
cCsvTable data; cCsvTable data;
if(!data.Load("mob_proto.txt",'\t')) { if(!data.Load("mob_proto.txt",'\t')) {
SPDLOG_ERROR("mob_proto.txt 파일을 읽어오지 못했습니다"); SPDLOG_ERROR("mob_proto.txt 파일을 읽어오지 못했습니다");
return false; return false;
} }
data.Next(); //설명 row 넘어가기 data.Next(); //설명 row 넘어가기
//2. (!)[mob_table] 생성하기 //2. (!)[mob_table] 생성하기
//2.1 새로 추가되는 갯수를 파악 //2.1 새로 추가되는 갯수를 파악
int addNumber = 0; int addNumber = 0;
while(data.Next()) { while(data.Next()) {
int vnum = atoi(data.AsStringByIndex(0)); int vnum = atoi(data.AsStringByIndex(0));
@ -279,15 +279,15 @@ bool CClientManager::InitializeMobTable()
addNumber++; addNumber++;
} }
} }
//data를 다시 첫줄로 옮긴다.(다시 읽어온다;;) //data를 다시 첫줄로 옮긴다.(다시 읽어온다;;)
data.Destroy(); data.Destroy();
if(!data.Load("mob_proto.txt",'\t')) if(!data.Load("mob_proto.txt",'\t'))
{ {
SPDLOG_ERROR("mob_proto.txt 파일을 읽어오지 못했습니다"); SPDLOG_ERROR("mob_proto.txt 파일을 읽어오지 못했습니다");
return false; return false;
} }
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분) data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
//2.2 크기에 맞게 mob_table 생성 //2.2 크기에 맞게 mob_table 생성
if (!m_vec_mobTable.empty()) if (!m_vec_mobTable.empty())
{ {
SPDLOG_DEBUG("RELOAD: mob_proto"); SPDLOG_DEBUG("RELOAD: mob_proto");
@ -296,18 +296,18 @@ bool CClientManager::InitializeMobTable()
m_vec_mobTable.resize(data.m_File.GetRowCount()-1 + addNumber); m_vec_mobTable.resize(data.m_File.GetRowCount()-1 + addNumber);
memset(&m_vec_mobTable[0], 0, sizeof(TMobTable) * m_vec_mobTable.size()); memset(&m_vec_mobTable[0], 0, sizeof(TMobTable) * m_vec_mobTable.size());
TMobTable * mob_table = &m_vec_mobTable[0]; TMobTable * mob_table = &m_vec_mobTable[0];
//2.3 데이터 채우기 //2.3 데이터 채우기
while (data.Next()) while (data.Next())
{ {
int col = 0; int col = 0;
//(b)[test_map_mobTableByVnum]에 같은 row가 있는지 조사. //(b)[test_map_mobTableByVnum]에 같은 row가 있는지 조사.
bool isSameRow = true; bool isSameRow = true;
std::map<DWORD, TMobTable *>::iterator it_map_mobTable; std::map<DWORD, TMobTable *>::iterator it_map_mobTable;
it_map_mobTable = test_map_mobTableByVnum.find(atoi(data.AsStringByIndex(col))); it_map_mobTable = test_map_mobTableByVnum.find(atoi(data.AsStringByIndex(col)));
if(it_map_mobTable == test_map_mobTableByVnum.end()) { if(it_map_mobTable == test_map_mobTableByVnum.end()) {
isSameRow = false; isSameRow = false;
} }
//같은 row 가 있으면 (b)에서 읽어온다. //같은 row 가 있으면 (b)에서 읽어온다.
if(isSameRow) { if(isSameRow) {
TMobTable *tempTable = it_map_mobTable->second; TMobTable *tempTable = it_map_mobTable->second;
@ -378,13 +378,13 @@ bool CClientManager::InitializeMobTable()
if (!Set_Proto_Mob_Table(mob_table, data, localMap)) if (!Set_Proto_Mob_Table(mob_table, data, localMap))
{ {
SPDLOG_ERROR("몹 프로토 테이블 셋팅 실패."); SPDLOG_ERROR("몹 프로토 테이블 셋팅 실패.");
} }
} }
//셋에 vnum 추가 //셋에 vnum 추가
vnumSet.insert(mob_table->dwVnum); vnumSet.insert(mob_table->dwVnum);
@ -395,22 +395,22 @@ bool CClientManager::InitializeMobTable()
//_____________________________________________________// //_____________________________________________________//
// 4) (b)[test_map_mobTableByVnum]의 row중, (!)[mob_table]에 없는 것을 추가한다. // 4) (b)[test_map_mobTableByVnum]의 row중, (!)[mob_table]에 없는 것을 추가한다.
//파일 다시 읽어오기. //파일 다시 읽어오기.
test_data.Destroy(); test_data.Destroy();
isTestFile = true; isTestFile = true;
test_data; test_data;
if(!test_data.Load("mob_proto_test.txt",'\t')) if(!test_data.Load("mob_proto_test.txt",'\t'))
{ {
SPDLOG_ERROR("테스트 파일이 없습니다. 그대로 진행합니다."); SPDLOG_ERROR("테스트 파일이 없습니다. 그대로 진행합니다.");
isTestFile = false; isTestFile = false;
} }
if(isTestFile) { if(isTestFile) {
test_data.Next(); //설명 로우 넘어가기. test_data.Next(); //설명 로우 넘어가기.
while (test_data.Next()) //테스트 데이터 각각을 훑어나가며,새로운 것을 추가한다. while (test_data.Next()) //테스트 데이터 각각을 훑어나가며,새로운 것을 추가한다.
{ {
//중복되는 부분이면 넘어간다. //중복되는 부분이면 넘어간다.
set<int>::iterator itVnum; set<int>::iterator itVnum;
itVnum=vnumSet.find(atoi(test_data.AsStringByIndex(0))); itVnum=vnumSet.find(atoi(test_data.AsStringByIndex(0)));
if (itVnum != vnumSet.end()) { if (itVnum != vnumSet.end()) {
@ -419,7 +419,7 @@ bool CClientManager::InitializeMobTable()
if (!Set_Proto_Mob_Table(mob_table, test_data, localMap)) if (!Set_Proto_Mob_Table(mob_table, test_data, localMap))
{ {
SPDLOG_ERROR("몹 프로토 테이블 셋팅 실패."); SPDLOG_ERROR("몹 프로토 테이블 셋팅 실패.");
} }
SPDLOG_DEBUG("MOB #{:<5} {:24} {:24} level: {:<3} rank: {} empire: {}", mob_table->dwVnum, mob_table->szName, mob_table->szLocaleName, mob_table->bLevel, mob_table->bRank, mob_table->bEmpire); SPDLOG_DEBUG("MOB #{:<5} {:24} {:24} level: {:<3} rank: {} empire: {}", mob_table->dwVnum, mob_table->szName, mob_table->szLocaleName, mob_table->bLevel, mob_table->bRank, mob_table->bEmpire);
@ -447,8 +447,8 @@ bool CClientManager::InitializeShopTable()
std::unique_ptr<SQLMsg> pkMsg2(CDBManager::instance().DirectQuery(s_szQuery)); std::unique_ptr<SQLMsg> pkMsg2(CDBManager::instance().DirectQuery(s_szQuery));
// shop의 vnum은 있는데 shop_item 이 없을경우... 실패로 처리되니 주의 요망. // shop의 vnum은 있는데 shop_item 이 없을경우... 실패로 처리되니 주의 요망.
// 고처야할부분 // 고처야할부분
SQLResult * pRes2 = pkMsg2->Get(); SQLResult * pRes2 = pkMsg2->Get();
if (!pRes2->uiNumRows) if (!pRes2->uiNumRows)
@ -487,7 +487,7 @@ bool CClientManager::InitializeShopTable()
str_to_number(shop_table->dwNPCVnum, data[col++]); str_to_number(shop_table->dwNPCVnum, data[col++]);
if (!data[col]) // 아이템이 하나도 없으면 NULL이 리턴 되므로.. if (!data[col]) // 아이템이 하나도 없으면 NULL이 리턴 되므로..
continue; continue;
TShopItemTable * pItem = &shop_table->items[shop_table->byItemCount]; TShopItemTable * pItem = &shop_table->items[shop_table->byItemCount];
@ -560,7 +560,7 @@ bool CClientManager::InitializeQuestItemTable()
continue; continue;
} }
tbl.bType = ITEM_QUEST; // quest_item_proto 테이블에 있는 것들은 모두 ITEM_QUEST 유형 tbl.bType = ITEM_QUEST; // quest_item_proto 테이블에 있는 것들은 모두 ITEM_QUEST 유형
tbl.bSize = 1; tbl.bSize = 1;
m_vec_itemTable.push_back(tbl); m_vec_itemTable.push_back(tbl);
@ -571,39 +571,39 @@ bool CClientManager::InitializeQuestItemTable()
bool CClientManager::InitializeItemTable() bool CClientManager::InitializeItemTable()
{ {
//================== 함수 설명 ==================// //================== 함수 설명 ==================//
//1. 요약 : 'item_proto.txt', 'item_proto_test.txt', 'item_names.txt' 파일을 읽고, //1. 요약 : 'item_proto.txt', 'item_proto_test.txt', 'item_names.txt' 파일을 읽고,
// <item_table>(TItemTable), <m_map_itemTableByVnum> 오브젝트를 생성한다. // <item_table>(TItemTable), <m_map_itemTableByVnum> 오브젝트를 생성한다.
//2. 순서 //2. 순서
// 1) 'item_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다. // 1) 'item_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
// 2) 'item_proto_text.txt'파일과 (a)[localMap] 맵으로 // 2) 'item_proto_text.txt'파일과 (a)[localMap] 맵으로
// (b)[test_map_itemTableByVnum](vnum:TItemTable) 맵을 생성한다. // (b)[test_map_itemTableByVnum](vnum:TItemTable) 맵을 생성한다.
// 3) 'item_proto.txt' 파일과 (a)[localMap] 맵으로 // 3) 'item_proto.txt' 파일과 (a)[localMap] 맵으로
// (!)[item_table], <m_map_itemTableByVnum>을 만든다. // (!)[item_table], <m_map_itemTableByVnum>을 만든다.
// <참고> // <참고>
// 각 row 들 중, // 각 row 들 중,
// (b)[test_map_itemTableByVnum],(!)[mob_table] 모두에 있는 row는 // (b)[test_map_itemTableByVnum],(!)[mob_table] 모두에 있는 row는
// (b)[test_map_itemTableByVnum]의 것을 사용한다. // (b)[test_map_itemTableByVnum]의 것을 사용한다.
// 4) (b)[test_map_itemTableByVnum]의 row중, (!)[item_table]에 없는 것을 추가한다. // 4) (b)[test_map_itemTableByVnum]의 row중, (!)[item_table]에 없는 것을 추가한다.
//3. 테스트 //3. 테스트
// 1)'item_proto.txt' 정보가 item_table에 잘 들어갔는지. -> 완료 // 1)'item_proto.txt' 정보가 item_table에 잘 들어갔는지. -> 완료
// 2)'item_names.txt' 정보가 item_table에 잘 들어갔는지. // 2)'item_names.txt' 정보가 item_table에 잘 들어갔는지.
// 3)'item_proto_test.txt' 에서 [겹치는] 정보가 item_table 에 잘 들어갔는지. // 3)'item_proto_test.txt' 에서 [겹치는] 정보가 item_table 에 잘 들어갔는지.
// 4)'item_proto_test.txt' 에서 [새로운] 정보가 item_table 에 잘 들어갔는지. // 4)'item_proto_test.txt' 에서 [새로운] 정보가 item_table 에 잘 들어갔는지.
// 5) (최종) 게임 클라이언트에서 제대로 작동 하는지. // 5) (최종) 게임 클라이언트에서 제대로 작동 하는지.
//_______________________________________________// //_______________________________________________//
//=================================================================================// //=================================================================================//
// 1) 'item_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다. // 1) 'item_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
//=================================================================================// //=================================================================================//
bool isNameFile = true; bool isNameFile = true;
map<int,const char*> localMap; map<int,const char*> localMap;
cCsvTable nameData; cCsvTable nameData;
if(!nameData.Load("item_names.txt",'\t')) if(!nameData.Load("item_names.txt",'\t'))
{ {
SPDLOG_ERROR("item_names.txt 파일을 읽어오지 못했습니다"); SPDLOG_ERROR("item_names.txt 파일을 읽어오지 못했습니다");
isNameFile = false; isNameFile = false;
} else { } else {
nameData.Next(); nameData.Next();
@ -614,32 +614,32 @@ bool CClientManager::InitializeItemTable()
//_________________________________________________________________// //_________________________________________________________________//
//=================================================================// //=================================================================//
// 2) 'item_proto_text.txt'파일과 (a)[localMap] 맵으로 // 2) 'item_proto_text.txt'파일과 (a)[localMap] 맵으로
// (b)[test_map_itemTableByVnum](vnum:TItemTable) 맵을 생성한다. // (b)[test_map_itemTableByVnum](vnum:TItemTable) 맵을 생성한다.
//=================================================================// //=================================================================//
map<DWORD, TItemTable *> test_map_itemTableByVnum; map<DWORD, TItemTable *> test_map_itemTableByVnum;
//1. 파일 읽어오기. //1. 파일 읽어오기.
cCsvTable test_data; cCsvTable test_data;
if(!test_data.Load("item_proto_test.txt",'\t')) if(!test_data.Load("item_proto_test.txt",'\t'))
{ {
SPDLOG_ERROR("item_proto_test.txt 파일을 읽어오지 못했습니다"); SPDLOG_ERROR("item_proto_test.txt 파일을 읽어오지 못했습니다");
//return false; //return false;
} else { } else {
test_data.Next(); //설명 로우 넘어가기. test_data.Next(); //설명 로우 넘어가기.
//2. 테스트 아이템 테이블 생성. //2. 테스트 아이템 테이블 생성.
TItemTable * test_item_table = NULL; TItemTable * test_item_table = NULL;
int test_itemTableSize = test_data.m_File.GetRowCount()-1; int test_itemTableSize = test_data.m_File.GetRowCount()-1;
test_item_table = new TItemTable[test_itemTableSize]; test_item_table = new TItemTable[test_itemTableSize];
memset(test_item_table, 0, sizeof(TItemTable) * test_itemTableSize); memset(test_item_table, 0, sizeof(TItemTable) * test_itemTableSize);
//3. 테스트 아이템 테이블에 값을 넣고, 맵에까지 넣기. //3. 테스트 아이템 테이블에 값을 넣고, 맵에까지 넣기.
while(test_data.Next()) { while(test_data.Next()) {
if (!Set_Proto_Item_Table(test_item_table, test_data, localMap)) if (!Set_Proto_Item_Table(test_item_table, test_data, localMap))
{ {
SPDLOG_ERROR("아이템 프로토 테이블 셋팅 실패."); SPDLOG_ERROR("아이템 프로토 테이블 셋팅 실패.");
} }
test_map_itemTableByVnum.insert(std::map<DWORD, TItemTable *>::value_type(test_item_table->dwVnum, test_item_table)); test_map_itemTableByVnum.insert(std::map<DWORD, TItemTable *>::value_type(test_item_table->dwVnum, test_item_table));
@ -651,25 +651,25 @@ bool CClientManager::InitializeItemTable()
//========================================================================// //========================================================================//
// 3) 'item_proto.txt' 파일과 (a)[localMap] 맵으로 // 3) 'item_proto.txt' 파일과 (a)[localMap] 맵으로
// (!)[item_table], <m_map_itemTableByVnum>을 만든다. // (!)[item_table], <m_map_itemTableByVnum>을 만든다.
// <참고> // <참고>
// 각 row 들 중, // 각 row 들 중,
// (b)[test_map_itemTableByVnum],(!)[mob_table] 모두에 있는 row는 // (b)[test_map_itemTableByVnum],(!)[mob_table] 모두에 있는 row는
// (b)[test_map_itemTableByVnum]의 것을 사용한다. // (b)[test_map_itemTableByVnum]의 것을 사용한다.
//========================================================================// //========================================================================//
//vnum들을 저장할 셋. 새로운 테스트 아이템을 판별할때 사용된다. //vnum들을 저장할 셋. 새로운 테스트 아이템을 판별할때 사용된다.
set<int> vnumSet; set<int> vnumSet;
//파일 읽어오기. //파일 읽어오기.
cCsvTable data; cCsvTable data;
if(!data.Load("item_proto.txt",'\t')) if(!data.Load("item_proto.txt",'\t'))
{ {
SPDLOG_ERROR("item_proto.txt 파일을 읽어오지 못했습니다"); SPDLOG_ERROR("item_proto.txt 파일을 읽어오지 못했습니다");
return false; return false;
} }
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분) data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
if (!m_vec_itemTable.empty()) if (!m_vec_itemTable.empty())
{ {
@ -678,8 +678,8 @@ bool CClientManager::InitializeItemTable()
m_map_itemTableByVnum.clear(); m_map_itemTableByVnum.clear();
} }
//===== 아이템 테이블 생성 =====// //===== 아이템 테이블 생성 =====//
//새로 추가되는 갯수를 파악한다. //새로 추가되는 갯수를 파악한다.
int addNumber = 0; int addNumber = 0;
while(data.Next()) { while(data.Next()) {
int vnum = atoi(data.AsStringByIndex(0)); int vnum = atoi(data.AsStringByIndex(0));
@ -689,14 +689,14 @@ bool CClientManager::InitializeItemTable()
addNumber++; addNumber++;
} }
} }
//data를 다시 첫줄로 옮긴다.(다시 읽어온다;;) //data를 다시 첫줄로 옮긴다.(다시 읽어온다;;)
data.Destroy(); data.Destroy();
if(!data.Load("item_proto.txt",'\t')) if(!data.Load("item_proto.txt",'\t'))
{ {
SPDLOG_ERROR("item_proto.txt 파일을 읽어오지 못했습니다"); SPDLOG_ERROR("item_proto.txt 파일을 읽어오지 못했습니다");
return false; return false;
} }
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분) data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
m_vec_itemTable.resize(data.m_File.GetRowCount() - 1 + addNumber); m_vec_itemTable.resize(data.m_File.GetRowCount() - 1 + addNumber);
memset(&m_vec_itemTable[0], 0, sizeof(TItemTable) * m_vec_itemTable.size()); memset(&m_vec_itemTable[0], 0, sizeof(TItemTable) * m_vec_itemTable.size());
@ -711,16 +711,16 @@ bool CClientManager::InitializeItemTable()
std::map<DWORD, TItemTable *>::iterator it_map_itemTable; std::map<DWORD, TItemTable *>::iterator it_map_itemTable;
it_map_itemTable = test_map_itemTableByVnum.find(atoi(data.AsStringByIndex(col))); it_map_itemTable = test_map_itemTableByVnum.find(atoi(data.AsStringByIndex(col)));
if(it_map_itemTable == test_map_itemTableByVnum.end()) { if(it_map_itemTable == test_map_itemTableByVnum.end()) {
//각 칼럼 데이터 저장 //각 칼럼 데이터 저장
if (!Set_Proto_Item_Table(item_table, data, localMap)) if (!Set_Proto_Item_Table(item_table, data, localMap))
{ {
SPDLOG_ERROR("아이템 프로토 테이블 셋팅 실패."); SPDLOG_ERROR("아이템 프로토 테이블 셋팅 실패.");
} }
} else { //$$$$$$$$$$$$$$$$$$$$$$$ 테스트 아이템 정보가 있다! } else { //$$$$$$$$$$$$$$$$$$$$$$$ 테스트 아이템 정보가 있다!
TItemTable *tempTable = it_map_itemTable->second; TItemTable *tempTable = it_map_itemTable->second;
item_table->dwVnum = tempTable->dwVnum; item_table->dwVnum = tempTable->dwVnum;
@ -777,19 +777,19 @@ bool CClientManager::InitializeItemTable()
//_______________________________________________________________________// //_______________________________________________________________________//
//========================================================================// //========================================================================//
// 4) (b)[test_map_itemTableByVnum]의 row중, (!)[item_table]에 없는 것을 추가한다. // 4) (b)[test_map_itemTableByVnum]의 row중, (!)[item_table]에 없는 것을 추가한다.
//========================================================================// //========================================================================//
test_data.Destroy(); test_data.Destroy();
if(!test_data.Load("item_proto_test.txt",'\t')) if(!test_data.Load("item_proto_test.txt",'\t'))
{ {
SPDLOG_ERROR("item_proto_test.txt 파일을 읽어오지 못했습니다"); SPDLOG_ERROR("item_proto_test.txt 파일을 읽어오지 못했습니다");
//return false; //return false;
} else { } else {
test_data.Next(); //설명 로우 넘어가기. test_data.Next(); //설명 로우 넘어가기.
while (test_data.Next()) //테스트 데이터 각각을 훑어나가며,새로운 것을 추가한다. while (test_data.Next()) //테스트 데이터 각각을 훑어나가며,새로운 것을 추가한다.
{ {
//중복되는 부분이면 넘어간다. //중복되는 부분이면 넘어간다.
set<int>::iterator itVnum; set<int>::iterator itVnum;
itVnum=vnumSet.find(atoi(test_data.AsStringByIndex(0))); itVnum=vnumSet.find(atoi(test_data.AsStringByIndex(0)));
if (itVnum != vnumSet.end()) { if (itVnum != vnumSet.end()) {
@ -798,7 +798,7 @@ bool CClientManager::InitializeItemTable()
if (!Set_Proto_Item_Table(item_table, test_data, localMap)) if (!Set_Proto_Item_Table(item_table, test_data, localMap))
{ {
SPDLOG_ERROR("아이템 프로토 테이블 셋팅 실패."); SPDLOG_ERROR("아이템 프로토 테이블 셋팅 실패.");
} }

View File

@ -126,13 +126,13 @@ const char* __GetWarType(int n)
switch (n) switch (n)
{ {
case 0 : case 0 :
return "패왕"; return "\xEF\xBF\xBD\xD0\xBF\xEF\xBF\xBD"; // 패왕
case 1 : case 1 :
return "맹장"; return "\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD"; // 맹장
case 2 : case 2 :
return "수호"; return "\xEF\xBF\xBD\xEF\xBF\xBD\xC8\xA3"; // 수호
default : default :
return "없는 번호"; return "\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\x20\xEF\xBF\xBD\xEF\xBF\xBD\xC8\xA3"; // 없는 번호
} }
} }
@ -161,7 +161,7 @@ void CClientManager::GuildWar(CPeer* peer, TPacketGuildWar* p)
case GUILD_WAR_WAIT_START: case GUILD_WAR_WAIT_START:
SPDLOG_DEBUG("GuildWar: GUILD_WAR_WAIT_START type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo); SPDLOG_DEBUG("GuildWar: GUILD_WAR_WAIT_START type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
case GUILD_WAR_RESERVE: // 길드전 예약 case GUILD_WAR_RESERVE: // 길드전 예약
if (p->bWar != GUILD_WAR_WAIT_START) if (p->bWar != GUILD_WAR_WAIT_START)
SPDLOG_DEBUG("GuildWar: GUILD_WAR_RESERVE type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo); SPDLOG_DEBUG("GuildWar: GUILD_WAR_RESERVE type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo); CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
@ -173,21 +173,21 @@ void CClientManager::GuildWar(CPeer* peer, TPacketGuildWar* p)
break; break;
case GUILD_WAR_ON_WAR: // 길드전을 시작 시킨다. (필드전은 바로 시작 됨) case GUILD_WAR_ON_WAR: // 길드전을 시작 시킨다. (필드전은 바로 시작 됨)
SPDLOG_DEBUG("GuildWar: GUILD_WAR_ON_WAR type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo); SPDLOG_DEBUG("GuildWar: GUILD_WAR_ON_WAR type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo); CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().StartWar(p->bType, p->dwGuildFrom, p->dwGuildTo); CGuildManager::instance().StartWar(p->bType, p->dwGuildFrom, p->dwGuildTo);
break; break;
case GUILD_WAR_OVER: // 길드전 정상 종료 case GUILD_WAR_OVER: // 길드전 정상 종료
SPDLOG_DEBUG("GuildWar: GUILD_WAR_OVER type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo); SPDLOG_DEBUG("GuildWar: GUILD_WAR_OVER type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().RecvWarOver(p->dwGuildFrom, p->dwGuildTo, p->bType, p->lWarPrice); CGuildManager::instance().RecvWarOver(p->dwGuildFrom, p->dwGuildTo, p->bType, p->lWarPrice);
break; break;
case GUILD_WAR_END: // 길드전 비정상 종료 case GUILD_WAR_END: // 길드전 비정상 종료
SPDLOG_DEBUG("GuildWar: GUILD_WAR_END type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo); SPDLOG_DEBUG("GuildWar: GUILD_WAR_END type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().RecvWarEnd(p->dwGuildFrom, p->dwGuildTo); CGuildManager::instance().RecvWarEnd(p->dwGuildFrom, p->dwGuildTo);
return; // NOTE: RecvWarEnd에서 패킷을 보내므로 따로 브로드캐스팅 하지 않는다. return; // NOTE: RecvWarEnd에서 패킷을 보내므로 따로 브로드캐스팅 하지 않는다.
case GUILD_WAR_CANCEL : case GUILD_WAR_CANCEL :
SPDLOG_DEBUG("GuildWar: GUILD_WAR_CANCEL type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo); SPDLOG_DEBUG("GuildWar: GUILD_WAR_CANCEL type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);

View File

@ -230,7 +230,7 @@ TAccountTable * CreateAccountTableFromRes(MYSQL_RES * res)
TAccountTable * pkTab = new TAccountTable; TAccountTable * pkTab = new TAccountTable;
memset(pkTab, 0, sizeof(TAccountTable)); memset(pkTab, 0, sizeof(TAccountTable));
// 첫번째 컬럼 것만 참고 한다 (JOIN QUERY를 위한 것 임) // 첫번째 컬럼 것만 참고 한다 (JOIN QUERY를 위한 것 임)
strlcpy(input_pwd, row[col++], sizeof(input_pwd)); strlcpy(input_pwd, row[col++], sizeof(input_pwd));
str_to_number(pkTab->id, row[col++]); str_to_number(pkTab->id, row[col++]);
strlcpy(pkTab->login, row[col++], sizeof(pkTab->login)); strlcpy(pkTab->login, row[col++], sizeof(pkTab->login));
@ -354,7 +354,7 @@ void CClientManager::RESULT_LOGIN(CPeer * peer, SQLMsg * msg)
if (info->account_index == 0) if (info->account_index == 0)
{ {
// 계정이 없네? // 계정이 없네?
if (msg->Get()->uiNumRows == 0) if (msg->Get()->uiNumRows == 0)
{ {
SPDLOG_DEBUG("RESULT_LOGIN: no account"); SPDLOG_DEBUG("RESULT_LOGIN: no account");
@ -396,14 +396,14 @@ void CClientManager::RESULT_LOGIN(CPeer * peer, SQLMsg * msg)
} }
else else
{ {
if (!info->pAccountTable) // 이럴리는 없겠지만;; if (!info->pAccountTable) // 이럴리는 없겠지만;;
{ {
peer->EncodeReturn(HEADER_DG_LOGIN_WRONG_PASSWD, info->dwHandle); peer->EncodeReturn(HEADER_DG_LOGIN_WRONG_PASSWD, info->dwHandle);
delete info; delete info;
return; return;
} }
// 다른 컨넥션이 이미 로그인 해버렸다면.. 이미 접속했다고 보내야 한다. // 다른 컨넥션이 이미 로그인 해버렸다면.. 이미 접속했다고 보내야 한다.
if (!InsertLogonAccount(info->pAccountTable->login, peer->GetHandle(), info->ip)) if (!InsertLogonAccount(info->pAccountTable->login, peer->GetHandle(), info->ip))
{ {
SPDLOG_DEBUG("RESULT_LOGIN: already logon {}", info->pAccountTable->login); SPDLOG_DEBUG("RESULT_LOGIN: already logon {}", info->pAccountTable->login);

View File

@ -31,7 +31,7 @@ bool CreateItemTableFromRes(MYSQL_RES * res, std::vector<TPlayerItem> * pVec, DW
int rows; int rows;
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음 if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
{ {
pVec->clear(); pVec->clear();
return true; return true;
@ -158,7 +158,7 @@ size_t CreatePlayerSaveQuery(char * pszQuery, size_t querySize, TPlayerTable * p
pkTab->horse.sStamina, pkTab->horse.sStamina,
pkTab->horse_skill_point); pkTab->horse_skill_point);
// Binary 로 바꾸기 위한 임시 공간 // Binary 로 바꾸기 위한 임시 공간
char text[8192 + 1]; char text[8192 + 1];
CDBManager::instance().EscapeString(text, pkTab->skills, sizeof(pkTab->skills)); CDBManager::instance().EscapeString(text, pkTab->skills, sizeof(pkTab->skills));
@ -210,7 +210,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
TPlayerTable * pTab; TPlayerTable * pTab;
// //
// 한 계정에 속한 모든 캐릭터들 캐쉬처리 // 한 계정에 속한 모든 캐릭터들 캐쉬처리
// //
CLoginData * pLoginData = GetLoginDataByAID(packet->account_id); CLoginData * pLoginData = GetLoginDataByAID(packet->account_id);
@ -222,12 +222,12 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
} }
//---------------------------------------------------------------- //----------------------------------------------------------------
// 1. 유저정보가 DBCache 에 존재 : DBCache에서 // 1. 유저정보가 DBCache 에 존재 : DBCache에서
// 2. 유저정보가 DBCache 에 없음 : DB에서 // 2. 유저정보가 DBCache 에 없음 : DB에서
// --------------------------------------------------------------- // ---------------------------------------------------------------
//---------------------------------- //----------------------------------
// 1. 유저정보가 DBCache 에 존재 : DBCache에서 // 1. 유저정보가 DBCache 에 존재 : DBCache에서
//---------------------------------- //----------------------------------
if ((c = GetPlayerCache(packet->player_id))) if ((c = GetPlayerCache(packet->player_id)))
{ {
@ -267,13 +267,13 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
SPDLOG_DEBUG("[PLAYER_LOAD] ID {} pid {} gold {} ", pTab->name, pTab->id, pTab->gold); SPDLOG_DEBUG("[PLAYER_LOAD] ID {} pid {} gold {} ", pTab->name, pTab->id, pTab->gold);
//-------------------------------------------- //--------------------------------------------
// 아이템 & AFFECT & QUEST 로딩 : // 아이템 & AFFECT & QUEST 로딩 :
//-------------------------------------------- //--------------------------------------------
// 1) 아이템이 DBCache 에 존재 : DBCache 에서 가져옴 // 1) 아이템이 DBCache 에 존재 : DBCache 에서 가져옴
// 2) 아이템이 DBCache 에 없음 : DB 에서 가져옴 // 2) 아이템이 DBCache 에 없음 : DB 에서 가져옴
///////////////////////////////////////////// /////////////////////////////////////////////
// 1) 아이템이 DBCache 에 존재 : DBCache 에서 가져옴 // 1) 아이템이 DBCache 에 존재 : DBCache 에서 가져옴
///////////////////////////////////////////// /////////////////////////////////////////////
if (pSet) if (pSet)
{ {
@ -288,7 +288,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
CItemCache * c = *it++; CItemCache * c = *it++;
TPlayerItem * p = c->Get(); TPlayerItem * p = c->Get();
if (p->vnum) // vnum이 없으면 삭제된 아이템이다. if (p->vnum) // vnum이 없으면 삭제된 아이템이다.
memcpy(&s_items[dwCount++], p, sizeof(TPlayerItem)); memcpy(&s_items[dwCount++], p, sizeof(TPlayerItem));
} }
@ -314,7 +314,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
CDBManager::instance().ReturnQuery(szQuery, QID_AFFECT, peer->GetHandle(), new ClientHandleInfo(dwHandle)); CDBManager::instance().ReturnQuery(szQuery, QID_AFFECT, peer->GetHandle(), new ClientHandleInfo(dwHandle));
} }
///////////////////////////////////////////// /////////////////////////////////////////////
// 2) 아이템이 DBCache 에 없음 : DB 에서 가져옴 // 2) 아이템이 DBCache 에 없음 : DB 에서 가져옴
///////////////////////////////////////////// /////////////////////////////////////////////
else else
{ {
@ -348,7 +348,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
//return; //return;
} }
//---------------------------------- //----------------------------------
// 2. 유저정보가 DBCache 에 없음 : DB에서 // 2. 유저정보가 DBCache 에 없음 : DB에서
//---------------------------------- //----------------------------------
else else
{ {
@ -357,7 +357,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
char queryStr[QUERY_MAX_LEN]; char queryStr[QUERY_MAX_LEN];
//-------------------------------------------------------------- //--------------------------------------------------------------
// 캐릭터 정보 얻어오기 : 무조건 DB에서 // 캐릭터 정보 얻어오기 : 무조건 DB에서
//-------------------------------------------------------------- //--------------------------------------------------------------
snprintf(queryStr, sizeof(queryStr), snprintf(queryStr, sizeof(queryStr),
"SELECT " "SELECT "
@ -373,7 +373,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
CDBManager::instance().ReturnQuery(queryStr, QID_PLAYER, peer->GetHandle(), pkInfo); CDBManager::instance().ReturnQuery(queryStr, QID_PLAYER, peer->GetHandle(), pkInfo);
//-------------------------------------------------------------- //--------------------------------------------------------------
// 아이템 가져오기 // 아이템 가져오기
//-------------------------------------------------------------- //--------------------------------------------------------------
snprintf(queryStr, sizeof(queryStr), 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 " "SELECT id,window+0,pos,count,vnum,socket0,socket1,socket2,attrtype0,attrvalue0,attrtype1,attrvalue1,attrtype2,attrvalue2,attrtype3,attrvalue3,attrtype4,attrvalue4,attrtype5,attrvalue5,attrtype6,attrvalue6 "
@ -382,15 +382,15 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
CDBManager::instance().ReturnQuery(queryStr, QID_ITEM, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id)); CDBManager::instance().ReturnQuery(queryStr, QID_ITEM, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id));
//-------------------------------------------------------------- //--------------------------------------------------------------
// QUEST 가져오기 // QUEST 가져오기
//-------------------------------------------------------------- //--------------------------------------------------------------
snprintf(queryStr, sizeof(queryStr), snprintf(queryStr, sizeof(queryStr),
"SELECT dwPID,szName,szState,lValue FROM quest%s WHERE dwPID=%d", "SELECT dwPID,szName,szState,lValue FROM quest%s WHERE dwPID=%d",
GetTablePostfix(), packet->player_id); GetTablePostfix(), packet->player_id);
CDBManager::instance().ReturnQuery(queryStr, QID_QUEST, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id,packet->account_id)); CDBManager::instance().ReturnQuery(queryStr, QID_QUEST, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id,packet->account_id));
//독일 선물 기능에서 item_award테이블에서 login 정보를 얻기위해 account id도 넘겨준다 //독일 선물 기능에서 item_award테이블에서 login 정보를 얻기위해 account id도 넘겨준다
//-------------------------------------------------------------- //--------------------------------------------------------------
// AFFECT 가져오기 // AFFECT 가져오기
//-------------------------------------------------------------- //--------------------------------------------------------------
snprintf(queryStr, sizeof(queryStr), snprintf(queryStr, sizeof(queryStr),
"SELECT dwPID,bType,bApplyOn,lApplyValue,dwFlag,lDuration,lSPCost FROM affect%s WHERE dwPID=%d", "SELECT dwPID,bType,bApplyOn,lApplyValue,dwFlag,lDuration,lSPCost FROM affect%s WHERE dwPID=%d",
@ -407,21 +407,21 @@ void CClientManager::ItemAward(CPeer * peer,char* login)
std::set<TItemAward *> * pSet = ItemAwardManager::instance().GetByLogin(login_t); std::set<TItemAward *> * pSet = ItemAwardManager::instance().GetByLogin(login_t);
if(pSet == NULL) if(pSet == NULL)
return; return;
typeof(pSet->begin()) it = pSet->begin(); //taken_time이 NULL인것들 읽어옴 typeof(pSet->begin()) it = pSet->begin(); //taken_time이 NULL인것들 읽어옴
while(it != pSet->end() ) while(it != pSet->end() )
{ {
TItemAward * pItemAward = *(it++); TItemAward * pItemAward = *(it++);
char* whyStr = pItemAward->szWhy; //why 콜룸 읽기 char* whyStr = pItemAward->szWhy; //why 콜룸 읽기
char cmdStr[100] = ""; //why콜룸에서 읽은 값을 임시 문자열에 복사해둠 char cmdStr[100] = ""; //why콜룸에서 읽은 값을 임시 문자열에 복사해둠
strcpy(cmdStr,whyStr); //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문 strcpy(cmdStr,whyStr); //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문
char command[20] = ""; char command[20] = "";
strcpy(command,GetCommand(cmdStr).c_str()); // command 얻기 strcpy(command,GetCommand(cmdStr).c_str()); // command 얻기
if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면 if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면
{ {
TPacketItemAwardInfromer giftData; TPacketItemAwardInfromer giftData;
strcpy(giftData.login, pItemAward->szLogin); //로그인 아이디 복사 strcpy(giftData.login, pItemAward->szLogin); //로그인 아이디 복사
strcpy(giftData.command, command); //명령어 복사 strcpy(giftData.command, command); //명령어 복사
giftData.vnum = pItemAward->dwVnum; //아이템 vnum도 복사 giftData.vnum = pItemAward->dwVnum; //아이템 vnum도 복사
ForwardPacket(HEADER_DG_ITEMAWARD_INFORMER,&giftData,sizeof(TPacketItemAwardInfromer)); ForwardPacket(HEADER_DG_ITEMAWARD_INFORMER,&giftData,sizeof(TPacketItemAwardInfromer));
} }
} }
@ -442,7 +442,7 @@ std::string CClientManager::GetCommand(char* str)
bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab) bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab)
{ {
if (mysql_num_rows(res) == 0) // 데이터 없음 if (mysql_num_rows(res) == 0) // 데이터 없음
return false; return false;
memset(pkTab, 0, sizeof(TPlayerTable)); memset(pkTab, 0, sizeof(TPlayerTable));
@ -529,11 +529,11 @@ bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab)
int max_point = pkTab->level - 9; int max_point = pkTab->level - 9;
int skill_point = int skill_point =
std::min<int>(20, pkTab->skills[121].bLevel) + // SKILL_LEADERSHIP 통솔력 std::min<int>(20, pkTab->skills[121].bLevel) + // SKILL_LEADERSHIP 통솔력
std::min<int>(20, pkTab->skills[124].bLevel) + // SKILL_MINING 채광 std::min<int>(20, pkTab->skills[124].bLevel) + // SKILL_MINING 채광
std::min<int>(10, pkTab->skills[131].bLevel) + // SKILL_HORSE_SUMMON 말소환 std::min<int>(10, pkTab->skills[131].bLevel) + // SKILL_HORSE_SUMMON 말소환
std::min<int>(20, pkTab->skills[141].bLevel) + // SKILL_ADD_HP HP보강 std::min<int>(20, pkTab->skills[141].bLevel) + // SKILL_ADD_HP HP보강
std::min<int>(20, pkTab->skills[142].bLevel); // SKILL_RESIST_PENETRATE 관통저항 std::min<int>(20, pkTab->skills[142].bLevel); // SKILL_RESIST_PENETRATE 관통저항
pkTab->sub_skill_point = max_point - skill_point; pkTab->sub_skill_point = max_point - skill_point;
} }
@ -573,13 +573,13 @@ void CClientManager::RESULT_COMPOSITE_PLAYER(CPeer * peer, SQLMsg * pMsg, DWORD
{ {
SPDLOG_DEBUG("QID_QUEST {}", info->dwHandle); SPDLOG_DEBUG("QID_QUEST {}", info->dwHandle);
RESULT_QUEST_LOAD(peer, pSQLResult, info->dwHandle, info->player_id); RESULT_QUEST_LOAD(peer, pSQLResult, info->dwHandle, info->player_id);
//aid얻기 //aid얻기
ClientHandleInfo* temp1 = info.get(); ClientHandleInfo* temp1 = info.get();
if (temp1 == NULL) if (temp1 == NULL)
break; break;
CLoginData* pLoginData1 = GetLoginDataByAID(temp1->account_id); // CLoginData* pLoginData1 = GetLoginDataByAID(temp1->account_id); //
//독일 선물 기능 //독일 선물 기능
if( pLoginData1->GetAccountRef().login == NULL) if( pLoginData1->GetAccountRef().login == NULL)
break; break;
if( pLoginData1 == NULL ) if( pLoginData1 == NULL )
@ -670,14 +670,14 @@ void CClientManager::RESULT_PLAYER_LOAD(CPeer * peer, MYSQL_RES * pRes, ClientHa
void CClientManager::RESULT_ITEM_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle, DWORD dwPID) void CClientManager::RESULT_ITEM_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle, DWORD dwPID)
{ {
static std::vector<TPlayerItem> s_items; static std::vector<TPlayerItem> s_items;
//DB에서 아이템 정보를 읽어온다. //DB에서 아이템 정보를 읽어온다.
CreateItemTableFromRes(pRes, &s_items, dwPID); CreateItemTableFromRes(pRes, &s_items, dwPID);
DWORD dwCount = s_items.size(); DWORD dwCount = s_items.size();
peer->EncodeHeader(HEADER_DG_ITEM_LOAD, dwHandle, sizeof(DWORD) + sizeof(TPlayerItem) * dwCount); peer->EncodeHeader(HEADER_DG_ITEM_LOAD, dwHandle, sizeof(DWORD) + sizeof(TPlayerItem) * dwCount);
peer->EncodeDWORD(dwCount); peer->EncodeDWORD(dwCount);
//CacheSet을 만든다 //CacheSet을 만든다
CreateItemCacheSet(dwPID); CreateItemCacheSet(dwPID);
// ITEM_LOAD_LOG_ATTACH_PID // ITEM_LOAD_LOG_ATTACH_PID
@ -689,7 +689,7 @@ void CClientManager::RESULT_ITEM_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHa
peer->Encode(&s_items[0], sizeof(TPlayerItem) * dwCount); peer->Encode(&s_items[0], sizeof(TPlayerItem) * dwCount);
for (DWORD i = 0; i < dwCount; ++i) for (DWORD i = 0; i < dwCount; ++i)
PutItemCache(&s_items[i], true); // 로드한 것은 따로 저장할 필요 없으므로, 인자 bSkipQuery에 true를 넣는다. PutItemCache(&s_items[i], true); // 로드한 것은 따로 저장할 필요 없으므로, 인자 bSkipQuery에 true를 넣는다.
} }
} }
@ -697,7 +697,7 @@ void CClientManager::RESULT_AFFECT_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dw
{ {
int iNumRows; int iNumRows;
if ((iNumRows = mysql_num_rows(pRes)) == 0) // 데이터 없음 if ((iNumRows = mysql_num_rows(pRes)) == 0) // 데이터 없음
return; return;
static std::vector<TPacketAffectElement> s_elements; static std::vector<TPacketAffectElement> s_elements;
@ -793,7 +793,7 @@ void CClientManager::__QUERY_PLAYER_CREATE(CPeer *peer, DWORD dwHandle, TPlayerC
int queryLen; int queryLen;
DWORD player_id; DWORD player_id;
// 한 계정에 X초 내로 캐릭터 생성을 할 수 없다. // 한 계정에 X초 내로 캐릭터 생성을 할 수 없다.
auto it = s_createTimeByAccountID.find(packet->account_id); auto it = s_createTimeByAccountID.find(packet->account_id);
if (it != s_createTimeByAccountID.end()) if (it != s_createTimeByAccountID.end())
@ -1022,7 +1022,7 @@ void CClientManager::__QUERY_PLAYER_DELETE(CPeer* peer, DWORD dwHandle, TPlayerD
} }
// //
// @version 05/06/10 Bang2ni - 플레이어 삭제시 가격정보 리스트 삭제 추가. // @version 05/06/10 Bang2ni - 플레이어 삭제시 가격정보 리스트 삭제 추가.
// //
void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg) void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
{ {
@ -1073,14 +1073,14 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
return; return;
} }
// 삭제 성공 // 삭제 성공
SPDLOG_DEBUG("PLAYER_DELETE SUCCESS {}", dwPID); SPDLOG_DEBUG("PLAYER_DELETE SUCCESS {}", dwPID);
char account_index_string[16]; char account_index_string[16];
snprintf(account_index_string, sizeof(account_index_string), "player_id%d", m_iPlayerIDStart + pi->account_index); snprintf(account_index_string, sizeof(account_index_string), "player_id%d", m_iPlayerIDStart + pi->account_index);
// 플레이어 테이블을 캐쉬에서 삭제한다. // 플레이어 테이블을 캐쉬에서 삭제한다.
CPlayerTableCache * pkPlayerCache = GetPlayerCache(pi->player_id); CPlayerTableCache * pkPlayerCache = GetPlayerCache(pi->player_id);
if (pkPlayerCache) if (pkPlayerCache)
@ -1089,7 +1089,7 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
delete pkPlayerCache; delete pkPlayerCache;
} }
// 아이템들을 캐쉬에서 삭제한다. // 아이템들을 캐쉬에서 삭제한다.
TItemCacheSet * pSet = GetItemCacheSet(pi->player_id); TItemCacheSet * pSet = GetItemCacheSet(pi->player_id);
if (pSet) if (pSet)
@ -1152,7 +1152,7 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
} }
else else
{ {
// 삭제 실패 // 삭제 실패
SPDLOG_DEBUG("PLAYER_DELETE FAIL NO ROW"); SPDLOG_DEBUG("PLAYER_DELETE FAIL NO ROW");
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1); peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
peer->EncodeBYTE(pi->account_index); peer->EncodeBYTE(pi->account_index);
@ -1237,7 +1237,7 @@ void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg)
if (res->uiNumRows == 0) if (res->uiNumRows == 0)
{ {
// 새로운 하이스코어를 삽입 // 새로운 하이스코어를 삽입
char buf[256]; char buf[256];
snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value); snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value);
CDBManager::instance().AsyncQuery(buf); CDBManager::instance().AsyncQuery(buf);
@ -1272,7 +1272,7 @@ void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg)
CDBManager::instance().AsyncQuery(buf); CDBManager::instance().AsyncQuery(buf);
} }
} }
// TODO: 이곳에서 하이스코어가 업데이트 되었는지 체크하여 공지를 뿌려야한다. // TODO: 이곳에서 하이스코어가 업데이트 되었는지 체크하여 공지를 뿌려야한다.
delete pi; delete pi;
} }
@ -1280,10 +1280,10 @@ void CClientManager::InsertLogoutPlayer(DWORD pid)
{ {
TLogoutPlayerMap::iterator it = m_map_logout.find(pid); TLogoutPlayerMap::iterator it = m_map_logout.find(pid);
// 존재하지 않을경우 추가 // 존재하지 않을경우 추가
if (it != m_map_logout.end()) if (it != m_map_logout.end())
{ {
// 존재할경우 시간만 갱신 // 존재할경우 시간만 갱신
SPDLOG_TRACE("LOGOUT: Update player time pid({})", pid); SPDLOG_TRACE("LOGOUT: Update player time pid({})", pid);
it->second->time = time(0); it->second->time = time(0);

View File

@ -67,7 +67,7 @@ bool CConfig::GetWord(FILE *fp, char *tar)
if ((c == ' ' || c == '\t' || c == '\n')) if ((c == ' ' || c == '\t' || c == '\n'))
{ {
// 텝. // 텝.
tar[i] = '\0'; tar[i] = '\0';
return true; return true;
} }
@ -144,7 +144,7 @@ bool CConfig::LoadFile(const char* filename)
} }
// 파일 닫는 부분. // 파일 닫는 부분.
fclose(fp); fclose(fp);
return true; return true;
} }

View File

@ -11,14 +11,14 @@
namespace namespace
{ {
/// 파싱용 state 열거값 /// 파싱용 state 열거값
enum ParseState enum ParseState
{ {
STATE_NORMAL = 0, ///< 일반 상태 STATE_NORMAL = 0, ///< 일반 상태
STATE_QUOTE ///< 따옴표 뒤의 상태 STATE_QUOTE ///< 따옴표 뒤의 상태
}; };
/// 문자열 좌우의 공백을 제거해서 반환한다. /// 문자열 좌우의 공백을 제거해서 반환한다.
std::string Trim(std::string str) std::string Trim(std::string str)
{ {
str = str.erase(str.find_last_not_of(" \t\r\n") + 1); str = str.erase(str.find_last_not_of(" \t\r\n") + 1);
@ -26,7 +26,7 @@ namespace
return str; return str;
} }
/// \brief 주어진 문장에 있는 알파벳을 모두 소문자로 바꾼다. /// \brief 주어진 문장에 있는 알파벳을 모두 소문자로 바꾼다.
std::string Lower(std::string original) std::string Lower(std::string original)
{ {
std::transform(original.begin(), original.end(), original.begin(), tolower); std::transform(original.begin(), original.end(), original.begin(), tolower);
@ -35,9 +35,9 @@ namespace
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 셀을 액세스할 때, 숫자 대신 사용할 이름을 등록한다. /// \brief 셀을 액세스할 때, 숫자 대신 사용할 이름을 등록한다.
/// \param name 셀 이름 /// \param name 셀 이름
/// \param index 셀 인덱스 /// \param index 셀 인덱스
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void cCsvAlias::AddAlias(const char* name, size_t index) void cCsvAlias::AddAlias(const char* name, size_t index)
{ {
@ -51,7 +51,7 @@ void cCsvAlias::AddAlias(const char* name, size_t index)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 모든 데이터를 삭제한다. /// \brief 모든 데이터를 삭제한다.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void cCsvAlias::Destroy() void cCsvAlias::Destroy()
{ {
@ -60,9 +60,9 @@ void cCsvAlias::Destroy()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 숫자 인덱스를 이름으로 변환한다. /// \brief 숫자 인덱스를 이름으로 변환한다.
/// \param index 숫자 인덱스 /// \param index 숫자 인덱스
/// \return const char* 이름 /// \return const char* 이름
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
const char* cCsvAlias::operator [] (size_t index) const const char* cCsvAlias::operator [] (size_t index) const
{ {
@ -78,9 +78,9 @@ const char* cCsvAlias::operator [] (size_t index) const
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 이름을 숫자 인덱스로 변환한다. /// \brief 이름을 숫자 인덱스로 변환한다.
/// \param name 이름 /// \param name 이름
/// \return size_t 숫자 인덱스 /// \return size_t 숫자 인덱스
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
size_t cCsvAlias::operator [] (const char* name) const size_t cCsvAlias::operator [] (const char* name) const
{ {
@ -96,11 +96,11 @@ size_t cCsvAlias::operator [] (const char* name) const
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 지정된 이름의 CSV 파일을 로드한다. /// \brief 지정된 이름의 CSV 파일을 로드한다.
/// \param fileName CSV 파일 이름 /// \param fileName CSV 파일 이름
/// \param seperator 필드 분리자로 사용할 글자. 기본값은 ','이다. /// \param seperator 필드 분리자로 사용할 글자. 기본값은 ','이다.
/// \param quote 따옴표로 사용할 글자. 기본값은 '"'이다. /// \param quote 따옴표로 사용할 글자. 기본값은 '"'이다.
/// \return bool 무사히 로드했다면 true, 아니라면 false /// \return bool 무사히 로드했다면 true, 아니라면 false
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool cCsvFile::Load(const char* fileName, const char seperator, const char quote) bool cCsvFile::Load(const char* fileName, const char seperator, const char quote)
{ {
@ -109,7 +109,7 @@ bool cCsvFile::Load(const char* fileName, const char seperator, const char quote
std::ifstream file(fileName, std::ios::in); std::ifstream file(fileName, std::ios::in);
if (!file) return false; if (!file) return false;
Destroy(); // 기존의 데이터를 삭제 Destroy(); // 기존의 데이터를 삭제
cCsvRow* row = NULL; cCsvRow* row = NULL;
ParseState state = STATE_NORMAL; ParseState state = STATE_NORMAL;
@ -124,33 +124,33 @@ bool cCsvFile::Load(const char* fileName, const char seperator, const char quote
std::string line(Trim(buf)); std::string line(Trim(buf));
if (line.empty() || (state == STATE_NORMAL && line[0] == '#')) continue; if (line.empty() || (state == STATE_NORMAL && line[0] == '#')) continue;
std::string text = std::string(line) + " "; // 파싱 lookahead 때문에 붙여준다. std::string text = std::string(line) + " "; // 파싱 lookahead 때문에 붙여준다.
size_t cur = 0; size_t cur = 0;
while (cur < text.size()) while (cur < text.size())
{ {
// 현재 모드가 QUOTE 모드일 때, // 현재 모드가 QUOTE 모드일 때,
if (state == STATE_QUOTE) if (state == STATE_QUOTE)
{ {
// '"' 문자의 종류는 두 가지이다. // '"' 문자의 종류는 두 가지이다.
// 1. 셀 내부에 특수 문자가 있을 경우 이를 알리는 셀 좌우의 것 // 1. 셀 내부에 특수 문자가 있을 경우 이를 알리는 셀 좌우의 것
// 2. 셀 내부의 '"' 문자가 '"' 2개로 치환된 것 // 2. 셀 내부의 '"' 문자가 '"' 2개로 치환된 것
// 이 중 첫번째 경우의 좌측에 있는 것은 CSV 파일이 정상적이라면, // 이 중 첫번째 경우의 좌측에 있는 것은 CSV 파일이 정상적이라면,
// 무조건 STATE_NORMAL에 걸리게 되어있다. // 무조건 STATE_NORMAL에 걸리게 되어있다.
// 그러므로 여기서 걸리는 것은 1번의 우측 경우나, 2번 경우 뿐이다. // 그러므로 여기서 걸리는 것은 1번의 우측 경우나, 2번 경우 뿐이다.
// 2번의 경우에는 무조건 '"' 문자가 2개씩 나타난다. 하지만 1번의 // 2번의 경우에는 무조건 '"' 문자가 2개씩 나타난다. 하지만 1번의
// 우측 경우에는 아니다. 이를 바탕으로 해서 코드를 짜면... // 우측 경우에는 아니다. 이를 바탕으로 해서 코드를 짜면...
if (text[cur] == quote) if (text[cur] == quote)
{ {
// 다음 문자가 '"' 문자라면, 즉 연속된 '"' 문자라면 // 다음 문자가 '"' 문자라면, 즉 연속된 '"' 문자라면
// 이는 셀 내부의 '"' 문자가 치환된 것이다. // 이는 셀 내부의 '"' 문자가 치환된 것이다.
if (text[cur+1] == quote) if (text[cur+1] == quote)
{ {
token += quote; token += quote;
++cur; ++cur;
} }
// 다음 문자가 '"' 문자가 아니라면 // 다음 문자가 '"' 문자가 아니라면
// 현재의 '"'문자는 셀의 끝을 알리는 문자라고 할 수 있다. // 현재의 '"'문자는 셀의 끝을 알리는 문자라고 할 수 있다.
else else
{ {
state = STATE_NORMAL; state = STATE_NORMAL;
@ -161,25 +161,25 @@ bool cCsvFile::Load(const char* fileName, const char seperator, const char quote
token += text[cur]; token += text[cur];
} }
} }
// 현재 모드가 NORMAL 모드일 때, // 현재 모드가 NORMAL 모드일 때,
else if (state == STATE_NORMAL) else if (state == STATE_NORMAL)
{ {
if (row == NULL) if (row == NULL)
row = new cCsvRow(); row = new cCsvRow();
// ',' 문자를 만났다면 셀의 끝의 의미한다. // ',' 문자를 만났다면 셀의 끝의 의미한다.
// 토큰으로서 셀 리스트에다가 집어넣고, 토큰을 초기화한다. // 토큰으로서 셀 리스트에다가 집어넣고, 토큰을 초기화한다.
if (text[cur] == seperator) if (text[cur] == seperator)
{ {
row->push_back(token); row->push_back(token);
token.clear(); token.clear();
} }
// '"' 문자를 만났다면, QUOTE 모드로 전환한다. // '"' 문자를 만났다면, QUOTE 모드로 전환한다.
else if (text[cur] == quote) else if (text[cur] == quote)
{ {
state = STATE_QUOTE; state = STATE_QUOTE;
} }
// 다른 일반 문자라면 현재 토큰에다가 덧붙인다. // 다른 일반 문자라면 현재 토큰에다가 덧붙인다.
else else
{ {
token += text[cur]; token += text[cur];
@ -189,8 +189,8 @@ bool cCsvFile::Load(const char* fileName, const char seperator, const char quote
++cur; ++cur;
} }
// 마지막 셀은 끝에 ',' 문자가 없기 때문에 여기서 추가해줘야한다. // 마지막 셀은 끝에 ',' 문자가 없기 때문에 여기서 추가해줘야한다.
// 단, 처음에 파싱 lookahead 때문에 붙인 스페이스 문자 두 개를 뗀다. // 단, 처음에 파싱 lookahead 때문에 붙인 스페이스 문자 두 개를 뗀다.
if (state == STATE_NORMAL) if (state == STATE_NORMAL)
{ {
Assert(row != NULL); Assert(row != NULL);
@ -209,49 +209,49 @@ bool cCsvFile::Load(const char* fileName, const char seperator, const char quote
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 가지고 있는 내용을 CSV 파일에다 저장한다. /// \brief 가지고 있는 내용을 CSV 파일에다 저장한다.
/// \param fileName CSV 파일 이름 /// \param fileName CSV 파일 이름
/// \param append true일 경우, 기존의 파일에다 덧붙인다. false인 경우에는 /// \param append true일 경우, 기존의 파일에다 덧붙인다. false인 경우에는
/// 기존의 파일 내용을 삭제하고, 새로 쓴다. /// 기존의 파일 내용을 삭제하고, 새로 쓴다.
/// \param seperator 필드 분리자로 사용할 글자. 기본값은 ','이다. /// \param seperator 필드 분리자로 사용할 글자. 기본값은 ','이다.
/// \param quote 따옴표로 사용할 글자. 기본값은 '"'이다. /// \param quote 따옴표로 사용할 글자. 기본값은 '"'이다.
/// \return bool 무사히 저장했다면 true, 에러가 생긴 경우에는 false /// \return bool 무사히 저장했다면 true, 에러가 생긴 경우에는 false
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quote) const bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quote) const
{ {
Assert(seperator != quote); Assert(seperator != quote);
// 출력 모드에 따라 파일을 적당한 플래그로 생성한다. // 출력 모드에 따라 파일을 적당한 플래그로 생성한다.
std::ofstream file; std::ofstream file;
if (append) { file.open(fileName, std::ios::out | std::ios::app); } if (append) { file.open(fileName, std::ios::out | std::ios::app); }
else { file.open(fileName, std::ios::out | std::ios::trunc); } else { file.open(fileName, std::ios::out | std::ios::trunc); }
// 파일을 열지 못했다면, false를 리턴한다. // 파일을 열지 못했다면, false를 리턴한다.
if (!file) return false; if (!file) return false;
char special_chars[5] = { seperator, quote, '\r', '\n', 0 }; char special_chars[5] = { seperator, quote, '\r', '\n', 0 };
char quote_escape_string[3] = { quote, quote, 0 }; char quote_escape_string[3] = { quote, quote, 0 };
// 모든 행을 횡단하면서... // 모든 행을 횡단하면서...
for (size_t i=0; i<m_Rows.size(); i++) for (size_t i=0; i<m_Rows.size(); i++)
{ {
const cCsvRow& row = *((*this)[i]); const cCsvRow& row = *((*this)[i]);
std::string line; std::string line;
// 행 안의 모든 토큰을 횡단하면서... // 행 안의 모든 토큰을 횡단하면서...
for (size_t j=0; j<row.size(); j++) for (size_t j=0; j<row.size(); j++)
{ {
const std::string& token = row[j]; const std::string& token = row[j];
// 일반적인('"' 또는 ','를 포함하지 않은) // 일반적인('"' 또는 ','를 포함하지 않은)
// 토큰이라면 그냥 저장하면 된다. // 토큰이라면 그냥 저장하면 된다.
if (token.find_first_of(special_chars) == std::string::npos) if (token.find_first_of(special_chars) == std::string::npos)
{ {
line += token; line += token;
} }
// 특수문자를 포함한 토큰이라면 문자열 좌우에 '"'를 붙여주고, // 특수문자를 포함한 토큰이라면 문자열 좌우에 '"'를 붙여주고,
// 문자열 내부의 '"'를 두 개로 만들어줘야한다. // 문자열 내부의 '"'를 두 개로 만들어줘야한다.
else else
{ {
line += quote; line += quote;
@ -265,11 +265,11 @@ bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quot
line += quote; line += quote;
} }
// 마지막 셀이 아니라면 ','를 토큰의 뒤에다 붙여줘야한다. // 마지막 셀이 아니라면 ','를 토큰의 뒤에다 붙여줘야한다.
if (j != row.size() - 1) { line += seperator; } if (j != row.size() - 1) { line += seperator; }
} }
// 라인을 출력한다. // 라인을 출력한다.
file << line << std::endl; file << line << std::endl;
} }
@ -277,7 +277,7 @@ bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quot
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 모든 데이터를 메모리에서 삭제한다. /// \brief 모든 데이터를 메모리에서 삭제한다.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void cCsvFile::Destroy() void cCsvFile::Destroy()
{ {
@ -288,9 +288,9 @@ void cCsvFile::Destroy()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 해당하는 인덱스의 행을 반환한다. /// \brief 해당하는 인덱스의 행을 반환한다.
/// \param index 인덱스 /// \param index 인덱스
/// \return cCsvRow* 해당 행 /// \return cCsvRow* 해당 행
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
cCsvRow* cCsvFile::operator [] (size_t index) cCsvRow* cCsvFile::operator [] (size_t index)
{ {
@ -299,9 +299,9 @@ cCsvRow* cCsvFile::operator [] (size_t index)
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 해당하는 인덱스의 행을 반환한다. /// \brief 해당하는 인덱스의 행을 반환한다.
/// \param index 인덱스 /// \param index 인덱스
/// \return const cCsvRow* 해당 행 /// \return const cCsvRow* 해당 행
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
const cCsvRow* cCsvFile::operator [] (size_t index) const const cCsvRow* cCsvFile::operator [] (size_t index) const
{ {
@ -310,7 +310,7 @@ const cCsvRow* cCsvFile::operator [] (size_t index) const
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 생성자 /// \brief 생성자
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
cCsvTable::cCsvTable() cCsvTable::cCsvTable()
: m_CurRow(-1) : m_CurRow(-1)
@ -318,18 +318,18 @@ cCsvTable::cCsvTable()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 소멸자 /// \brief 소멸자
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
cCsvTable::~cCsvTable() cCsvTable::~cCsvTable()
{ {
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 지정된 이름의 CSV 파일을 로드한다. /// \brief 지정된 이름의 CSV 파일을 로드한다.
/// \param fileName CSV 파일 이름 /// \param fileName CSV 파일 이름
/// \param seperator 필드 분리자로 사용할 글자. 기본값은 ','이다. /// \param seperator 필드 분리자로 사용할 글자. 기본값은 ','이다.
/// \param quote 따옴표로 사용할 글자. 기본값은 '"'이다. /// \param quote 따옴표로 사용할 글자. 기본값은 '"'이다.
/// \return bool 무사히 로드했다면 true, 아니라면 false /// \return bool 무사히 로드했다면 true, 아니라면 false
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool cCsvTable::Load(const char* fileName, const char seperator, const char quote) bool cCsvTable::Load(const char* fileName, const char seperator, const char quote)
{ {
@ -338,19 +338,19 @@ bool cCsvTable::Load(const char* fileName, const char seperator, const char quot
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 다음 행으로 넘어간다. /// \brief 다음 행으로 넘어간다.
/// \return bool 다음 행으로 무사히 넘어간 경우 true를 반환하고, 더 이상 /// \return bool 다음 행으로 무사히 넘어간 경우 true를 반환하고, 더 이상
/// 넘어갈 행이 존재하지 않는 경우에는 false를 반환한다. /// 넘어갈 행이 존재하지 않는 경우에는 false를 반환한다.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool cCsvTable::Next() bool cCsvTable::Next()
{ {
// 20억번 정도 호출하면 오버플로가 일어날텐데...괜찮겠지? // 20억번 정도 호출하면 오버플로가 일어날텐데...괜찮겠지?
return ++m_CurRow < (int)m_File.GetRowCount() ? true : false; return ++m_CurRow < (int)m_File.GetRowCount() ? true : false;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 현재 행의 셀 숫자를 반환한다. /// \brief 현재 행의 셀 숫자를 반환한다.
/// \return size_t 현재 행의 셀 숫자 /// \return size_t 현재 행의 셀 숫자
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
size_t cCsvTable::ColCount() const size_t cCsvTable::ColCount() const
{ {
@ -358,9 +358,9 @@ size_t cCsvTable::ColCount() const
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 인덱스를 이용해 int 형으로 셀 값을 반환한다. /// \brief 인덱스를 이용해 int 형으로 셀 값을 반환한다.
/// \param index 셀 인덱스 /// \param index 셀 인덱스
/// \return int 셀 값 /// \return int 셀 값
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int cCsvTable::AsInt(size_t index) const int cCsvTable::AsInt(size_t index) const
{ {
@ -371,9 +371,9 @@ int cCsvTable::AsInt(size_t index) const
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 인덱스를 이용해 double 형으로 셀 값을 반환한다. /// \brief 인덱스를 이용해 double 형으로 셀 값을 반환한다.
/// \param index 셀 인덱스 /// \param index 셀 인덱스
/// \return double 셀 값 /// \return double 셀 값
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
double cCsvTable::AsDouble(size_t index) const double cCsvTable::AsDouble(size_t index) const
{ {
@ -384,9 +384,9 @@ double cCsvTable::AsDouble(size_t index) const
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 인덱스를 이용해 std::string 형으로 셀 값을 반환한다. /// \brief 인덱스를 이용해 std::string 형으로 셀 값을 반환한다.
/// \param index 셀 인덱스 /// \param index 셀 인덱스
/// \return const char* 셀 값 /// \return const char* 셀 값
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
const char* cCsvTable::AsStringByIndex(size_t index) const const char* cCsvTable::AsStringByIndex(size_t index) const
{ {
@ -397,7 +397,7 @@ const char* cCsvTable::AsStringByIndex(size_t index) const
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief alias를 포함해 모든 데이터를 삭제한다. /// \brief alias를 포함해 모든 데이터를 삭제한다.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void cCsvTable::Destroy() void cCsvTable::Destroy()
{ {
@ -407,10 +407,10 @@ void cCsvTable::Destroy()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// \brief 현재 행을 반환한다. /// \brief 현재 행을 반환한다.
/// \return const cCsvRow* 액세스가 가능한 현재 행이 존재하는 경우에는 그 행의 /// \return const cCsvRow* 액세스가 가능한 현재 행이 존재하는 경우에는 그 행의
/// 포인터를 반환하고, 더 이상 액세스 가능한 행이 없는 경우에는 NULL을 /// 포인터를 반환하고, 더 이상 액세스 가능한 행이 없는 경우에는 NULL을
/// 반환한다. /// 반환한다.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
const cCsvRow* const cCsvTable::CurRow() const const cCsvRow* const cCsvTable::CurRow() const
{ {

View File

@ -242,7 +242,7 @@ void CGuildManager::ResultRanking(MYSQL_RES * pRes)
void CGuildManager::Update() void CGuildManager::Update()
{ {
ProcessReserveWar(); // 예약 전쟁 처리 ProcessReserveWar(); // 예약 전쟁 처리
time_t now = CClientManager::instance().GetCurrentTime(); time_t now = CClientManager::instance().GetCurrentTime();
@ -462,7 +462,7 @@ void CGuildManager::RemoveWar(DWORD GID1, DWORD GID2)
} }
// //
// 길드전 비정상 종료 및 필드전 종료 // 길드전 비정상 종료 및 필드전 종료
// //
void CGuildManager::WarEnd(DWORD GID1, DWORD GID2, bool bForceDraw) void CGuildManager::WarEnd(DWORD GID1, DWORD GID2, bool bForceDraw)
{ {
@ -493,7 +493,7 @@ void CGuildManager::WarEnd(DWORD GID1, DWORD GID2, bool bForceDraw)
bool bDraw = false; bool bDraw = false;
if (!bForceDraw) // 강제 무승부가 아닐 경우에는 점수를 체크한다. if (!bForceDraw) // 강제 무승부가 아닐 경우에는 점수를 체크한다.
{ {
if (pData->iScore[0] > pData->iScore[1]) if (pData->iScore[0] > pData->iScore[1])
{ {
@ -508,7 +508,7 @@ void CGuildManager::WarEnd(DWORD GID1, DWORD GID2, bool bForceDraw)
else else
bDraw = true; bDraw = true;
} }
else // 강제 무승부일 경우에는 무조건 무승부 else // 강제 무승부일 경우에는 무조건 무승부
bDraw = true; bDraw = true;
if (bDraw) if (bDraw)
@ -516,14 +516,14 @@ void CGuildManager::WarEnd(DWORD GID1, DWORD GID2, bool bForceDraw)
else else
ProcessWinLose(win_guild, lose_guild); ProcessWinLose(win_guild, lose_guild);
// DB 서버에서 자체적으로 끝낼 때도 있기 때문에 따로 패킷을 보내줘야 한다. // DB 서버에서 자체적으로 끝낼 때도 있기 때문에 따로 패킷을 보내줘야 한다.
CClientManager::instance().for_each_peer(FSendPeerWar(0, GUILD_WAR_END, GID1, GID2)); CClientManager::instance().for_each_peer(FSendPeerWar(0, GUILD_WAR_END, GID1, GID2));
RemoveWar(GID1, GID2); RemoveWar(GID1, GID2);
} }
// //
// 길드전 정상 종료 // 길드전 정상 종료
// //
void CGuildManager::RecvWarOver(DWORD dwGuildWinner, DWORD dwGuildLoser, bool bDraw, int lWarPrice) void CGuildManager::RecvWarOver(DWORD dwGuildWinner, DWORD dwGuildLoser, bool bDraw, int lWarPrice)
{ {
@ -571,7 +571,7 @@ void CGuildManager::RecvWarOver(DWORD dwGuildWinner, DWORD dwGuildLoser, bool bD
void CGuildManager::RecvWarEnd(DWORD GID1, DWORD GID2) void CGuildManager::RecvWarEnd(DWORD GID1, DWORD GID2)
{ {
SPDLOG_DEBUG("GuildWar: RecvWarEnded : {} vs {}", GID1, GID2); SPDLOG_DEBUG("GuildWar: RecvWarEnded : {} vs {}", GID1, GID2);
WarEnd(GID1, GID2, true); // 무조건 비정상 종료 시켜야 한다. WarEnd(GID1, GID2, true); // 무조건 비정상 종료 시켜야 한다.
} }
void CGuildManager::StartWar(BYTE bType, DWORD GID1, DWORD GID2, CGuildWarReserve * pkReserve) void CGuildManager::StartWar(BYTE bType, DWORD GID1, DWORD GID2, CGuildWarReserve * pkReserve)
@ -745,7 +745,7 @@ void CGuildManager::ChangeLadderPoint(DWORD GID, int change)
SPDLOG_DEBUG("GuildManager::ChangeLadderPoint {} {}", GID, r.ladder_point); SPDLOG_DEBUG("GuildManager::ChangeLadderPoint {} {}", GID, r.ladder_point);
SPDLOG_DEBUG("{}", buf); SPDLOG_DEBUG("{}", buf);
// Packet 보내기 // Packet 보내기
TPacketGuildLadder p; TPacketGuildLadder p;
p.dwGuild = GID; p.dwGuild = GID;
@ -808,7 +808,7 @@ void CGuildManager::WithdrawMoney(CPeer* peer, DWORD dwGuild, INT iGold)
return; return;
} }
// 돈이있으니 출금하고 올려준다 // 돈이있으니 출금하고 올려준다
if (it->second.gold >= iGold) if (it->second.gold >= iGold)
{ {
it->second.gold -= iGold; it->second.gold -= iGold;
@ -839,7 +839,7 @@ void CGuildManager::WithdrawMoneyReply(DWORD dwGuild, BYTE bGiveSuccess, INT iGo
} }
// //
// 예약 길드전(관전자가 배팅할 수 있다) // 예약 길드전(관전자가 배팅할 수 있다)
// //
const int c_aiScoreByLevel[GUILD_MAX_LEVEL+1] = const int c_aiScoreByLevel[GUILD_MAX_LEVEL+1] =
{ {
@ -869,7 +869,7 @@ const int c_aiScoreByLevel[GUILD_MAX_LEVEL+1] =
const int c_aiScoreByRanking[GUILD_RANK_MAX_NUM+1] = const int c_aiScoreByRanking[GUILD_RANK_MAX_NUM+1] =
{ {
0, 0,
55000, // 1위 55000, // 1위
50000, 50000,
45000, 45000,
40000, 40000,
@ -878,7 +878,7 @@ const int c_aiScoreByRanking[GUILD_RANK_MAX_NUM+1] =
28000, 28000,
24000, 24000,
21000, 21000,
18000, // 10위 18000, // 10위
15000, 15000,
12000, 12000,
10000, 10000,
@ -888,7 +888,7 @@ const int c_aiScoreByRanking[GUILD_RANK_MAX_NUM+1] =
3000, 3000,
2000, 2000,
1000, 1000,
500 // 20위 500 // 20위
}; };
void CGuildManager::BootReserveWar() void CGuildManager::BootReserveWar()
@ -932,8 +932,8 @@ void CGuildManager::BootReserveWar()
char buf[512]; char buf[512];
snprintf(buf, sizeof(buf), "GuildWar: BootReserveWar : step %d id %u GID1 %u GID2 %u", i, t.dwID, t.dwGuildFrom, t.dwGuildTo); snprintf(buf, sizeof(buf), "GuildWar: BootReserveWar : step %d id %u GID1 %u GID2 %u", i, t.dwID, t.dwGuildFrom, t.dwGuildTo);
// i == 0 이면 길드전 도중 DB가 튕긴 것이므로 무승부 처리한다. // i == 0 이면 길드전 도중 DB가 튕긴 것이므로 무승부 처리한다.
// 또는, 5분 이하 남은 예약 길드전도 무승부 처리한다. (각자의 배팅액을 돌려준다) // 또는, 5분 이하 남은 예약 길드전도 무승부 처리한다. (각자의 배팅액을 돌려준다)
//if (i == 0 || (int) t.dwTime - CClientManager::instance().GetCurrentTime() < 60 * 5) //if (i == 0 || (int) t.dwTime - CClientManager::instance().GetCurrentTime() < 60 * 5)
if (i == 0 || (int) t.dwTime - CClientManager::instance().GetCurrentTime() < 0) if (i == 0 || (int) t.dwTime - CClientManager::instance().GetCurrentTime() < 0)
{ {
@ -1010,7 +1010,7 @@ bool CGuildManager::ReserveWar(TPacketGuildWar * p)
int lvp, rkp, alv, mc; int lvp, rkp, alv, mc;
// 파워 계산 // 파워 계산
TGuild & k1 = TouchGuild(GID1); TGuild & k1 = TouchGuild(GID1);
lvp = c_aiScoreByLevel[std::min<size_t>(GUILD_MAX_LEVEL, k1.level)]; lvp = c_aiScoreByLevel[std::min<size_t>(GUILD_MAX_LEVEL, k1.level)];
@ -1026,7 +1026,7 @@ bool CGuildManager::ReserveWar(TPacketGuildWar * p)
t.lPowerFrom = (int) polyPower.Eval(); t.lPowerFrom = (int) polyPower.Eval();
SPDLOG_DEBUG("GuildWar: {} lvp {} rkp {} alv {} mc {} power {}", GID1, lvp, rkp, alv, mc, t.lPowerFrom); SPDLOG_DEBUG("GuildWar: {} lvp {} rkp {} alv {} mc {} power {}", GID1, lvp, rkp, alv, mc, t.lPowerFrom);
// 파워 계산 // 파워 계산
TGuild & k2 = TouchGuild(GID2); TGuild & k2 = TouchGuild(GID2);
lvp = c_aiScoreByLevel[std::min<size_t>(GUILD_MAX_LEVEL, k2.level)]; lvp = c_aiScoreByLevel[std::min<size_t>(GUILD_MAX_LEVEL, k2.level)];
@ -1042,7 +1042,7 @@ bool CGuildManager::ReserveWar(TPacketGuildWar * p)
t.lPowerTo = (int) polyPower.Eval(); t.lPowerTo = (int) polyPower.Eval();
SPDLOG_DEBUG("GuildWar: {} lvp {} rkp {} alv {} mc {} power {}", GID2, lvp, rkp, alv, mc, t.lPowerTo); SPDLOG_DEBUG("GuildWar: {} lvp {} rkp {} alv {} mc {} power {}", GID2, lvp, rkp, alv, mc, t.lPowerTo);
// 핸디캡 계산 // 핸디캡 계산
if (t.lPowerTo > t.lPowerFrom) if (t.lPowerTo > t.lPowerFrom)
{ {
polyHandicap.SetVar("pA", t.lPowerTo); polyHandicap.SetVar("pA", t.lPowerTo);
@ -1057,7 +1057,7 @@ bool CGuildManager::ReserveWar(TPacketGuildWar * p)
t.lHandicap = (int) polyHandicap.Eval(); t.lHandicap = (int) polyHandicap.Eval();
SPDLOG_DEBUG("GuildWar: handicap {}", t.lHandicap); SPDLOG_DEBUG("GuildWar: handicap {}", t.lHandicap);
// 쿼리 // 쿼리
char szQuery[512]; char szQuery[512];
snprintf(szQuery, sizeof(szQuery), snprintf(szQuery, sizeof(szQuery),
@ -1094,7 +1094,7 @@ void CGuildManager::ProcessReserveWar()
CGuildWarReserve * pk = it2->second; CGuildWarReserve * pk = it2->second;
TGuildWarReserve & r = pk->GetDataRef(); TGuildWarReserve & r = pk->GetDataRef();
if (!r.bStarted && r.dwTime - 1800 <= dwCurTime) // 30분 전부터 알린다. if (!r.bStarted && r.dwTime - 1800 <= dwCurTime) // 30분 전부터 알린다.
{ {
int iMin = (int) ceil((int)(r.dwTime - dwCurTime) / 60.0); int iMin = (int) ceil((int)(r.dwTime - dwCurTime) / 60.0);
@ -1135,9 +1135,11 @@ void CGuildManager::ProcessReserveWar()
pk->SetLastNoticeMin(iMin); pk->SetLastNoticeMin(iMin);
if (!g_stLocale.compare("euckr")) if (!g_stLocale.compare("euckr"))
CClientManager::instance().SendNotice("%s 길드와 %s 길드의 전쟁이 약 %d분 후 시작 됩니다!", r_1.szName, r_2.szName, iMin); // "%s 길드와 %s 길드의 전쟁이 약 %d분 후 시작 됩니다!"
CClientManager::instance().SendNotice("%s \xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD %s \xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD \xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD \xEF\xBF\xBD\xEF\xBF\xBD %d\xEF\xBF\xBD\xEF\xBF\xBD \xEF\xBF\xBD\xEF\xBF\xBD \xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD \xEF\xBF\xBD\xCB\xB4\xCF\xB4\xEF\xBF\xBD!", r_1.szName, r_2.szName, iMin);
else if (!g_stLocale.compare("gb2312")) else if (!g_stLocale.compare("gb2312"))
CClientManager::instance().SendNotice("%s 곤삔뵨 %s 곤삔돨곤삔濫轢쉥瞳 %d롸爐빈역迦!", r_1.szName, r_2.szName, iMin); // "%s 곤삔뵨 %s 곤삔돨곤삔濫轢쉥瞳 %d롸爐빈역迦!"
CClientManager::instance().SendNotice("%s \xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD %s \xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xC4\xB0\xEF\xBF\xBD\xEF\xBF\xBD\xD5\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD %d\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xD3\xBA\xEF\xBF\xBD\xCA\xBC!", r_1.szName, r_2.szName, iMin);
} }
} }
} }
@ -1239,7 +1241,7 @@ void CGuildWarReserve::Initialize()
void CGuildWarReserve::OnSetup(CPeer * peer) void CGuildWarReserve::OnSetup(CPeer * peer)
{ {
if (m_data.bStarted) // 이미 시작된 것은 보내지 않는다. if (m_data.bStarted) // 이미 시작된 것은 보내지 않는다.
return; return;
FSendPeerWar(m_data.bType, GUILD_WAR_RESERVE, m_data.dwGuildFrom, m_data.dwGuildTo) (peer); FSendPeerWar(m_data.bType, GUILD_WAR_RESERVE, m_data.dwGuildFrom, m_data.dwGuildTo) (peer);
@ -1325,8 +1327,8 @@ bool CGuildWarReserve::Bet(const char * pszLogin, DWORD dwGold, DWORD dwGuild)
} }
// //
// 무승부 처리: 대부분 승부가 나야 정상이지만, 서버 문제 등 특정 상황일 경우에는 // 무승부 처리: 대부분 승부가 나야 정상이지만, 서버 문제 등 특정 상황일 경우에는
// 무승부 처리가 있어야 한다. // 무승부 처리가 있어야 한다.
// //
void CGuildWarReserve::Draw() void CGuildWarReserve::Draw()
{ {
@ -1458,7 +1460,7 @@ void CGuildWarReserve::End(int iScoreFrom, int iScoreTo)
double ratio = (double) it->second.second / dwWinnerBet; double ratio = (double) it->second.second / dwWinnerBet;
// 10% 세금 공제 후 분배 // 10% 세금 공제 후 분배
SPDLOG_DEBUG("WAR_REWARD: {} {} ratio {}", it->first.c_str(), it->second.second, ratio); SPDLOG_DEBUG("WAR_REWARD: {} {} ratio {}", it->first.c_str(), it->second.second, ratio);
DWORD dwGold = (DWORD) (dwTotalBet * ratio * 0.9); DWORD dwGold = (DWORD) (dwTotalBet * ratio * 0.9);

View File

@ -30,7 +30,7 @@ bool PlayerHB::Initialize()
} }
// //
// @version 05/07/05 Bang2ni - id 에 해당하는 data 가 없을 때 쿼리하고 data 를 insert 하는코드 추가. // @version 05/07/05 Bang2ni - id 에 해당하는 data 가 없을 때 쿼리하고 data 를 insert 하는코드 추가.
// //
void PlayerHB::Put(DWORD id) void PlayerHB::Put(DWORD id)
{ {
@ -48,7 +48,7 @@ void PlayerHB::Put(DWORD id)
} }
// //
// @version 05/07/05 Bang2ni - Query string 버퍼가 작아서 늘려줌. // @version 05/07/05 Bang2ni - Query string 버퍼가 작아서 늘려줌.
// //
bool PlayerHB::Query(DWORD id) bool PlayerHB::Query(DWORD id)
{ {

View File

@ -54,19 +54,19 @@ void ItemAwardManager::Load(SQLMsg * pMsg)
if (row[col]) if (row[col])
{ {
strlcpy(kData->szWhy, row[col], sizeof(kData->szWhy)); strlcpy(kData->szWhy, row[col], sizeof(kData->szWhy));
//게임 중에 why콜룸에 변동이 생기면 //게임 중에 why콜룸에 변동이 생기면
char* whyStr = kData->szWhy; //why 콜룸 읽기 char* whyStr = kData->szWhy; //why 콜룸 읽기
char cmdStr[100] = ""; //why콜룸에서 읽은 값을 임시 문자열에 복사해둠 char cmdStr[100] = ""; //why콜룸에서 읽은 값을 임시 문자열에 복사해둠
strcpy(cmdStr,whyStr); //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문 strcpy(cmdStr,whyStr); //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문
char command[20] = ""; char command[20] = "";
strcpy(command,CClientManager::instance().GetCommand(cmdStr).c_str()); // command 얻기 strcpy(command,CClientManager::instance().GetCommand(cmdStr).c_str()); // command 얻기
//SPDLOG_ERROR("{}, {}",pItemAward->dwID,command); //SPDLOG_ERROR("{}, {}",pItemAward->dwID,command);
if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면 if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면
{ {
TPacketItemAwardInfromer giftData; TPacketItemAwardInfromer giftData;
strcpy(giftData.login, kData->szLogin); //로그인 아이디 복사 strcpy(giftData.login, kData->szLogin); //로그인 아이디 복사
strcpy(giftData.command, command); //명령어 복사 strcpy(giftData.command, command); //명령어 복사
giftData.vnum = kData->dwVnum; //아이템 vnum도 복사 giftData.vnum = kData->dwVnum; //아이템 vnum도 복사
CClientManager::instance().ForwardPacket(HEADER_DG_ITEMAWARD_INFORMER,&giftData,sizeof(TPacketItemAwardInfromer)); CClientManager::instance().ForwardPacket(HEADER_DG_ITEMAWARD_INFORMER,&giftData,sizeof(TPacketItemAwardInfromer));
} }
} }

View File

@ -31,11 +31,11 @@ std::string g_stPlayerDBName = "";
bool g_bHotBackup = false; bool g_bHotBackup = false;
BOOL g_test_server = false; BOOL g_test_server = false;
//단위 초 //단위 초
int g_iPlayerCacheFlushSeconds = 60*7; int g_iPlayerCacheFlushSeconds = 60*7;
int g_iItemCacheFlushSeconds = 60*5; int g_iItemCacheFlushSeconds = 60*5;
//g_iLogoutSeconds 수치는 g_iPlayerCacheFlushSeconds 와 g_iItemCacheFlushSeconds 보다 길어야 한다. //g_iLogoutSeconds 수치는 g_iPlayerCacheFlushSeconds 와 g_iItemCacheFlushSeconds 보다 길어야 한다.
int g_iLogoutSeconds = 60*10; int g_iLogoutSeconds = 60*10;
@ -122,13 +122,13 @@ int main()
void emptybeat(LPHEART heart, int pulse) void emptybeat(LPHEART heart, int pulse)
{ {
if (!(pulse % heart->passes_per_sec)) // 1초에 한번 if (!(pulse % heart->passes_per_sec)) // 1초에 한번
{ {
} }
} }
// //
// @version 05/06/13 Bang2ni - 아이템 가격정보 캐시 flush timeout 설정 추가. // @version 05/06/13 Bang2ni - 아이템 가격정보 캐시 flush timeout 설정 추가.
// //
int Start() int Start()
{ {

View File

@ -253,7 +253,7 @@ namespace marriage
void CManager::OnSetup(CPeer* peer) void CManager::OnSetup(CPeer* peer)
{ {
// 결혼한 사람들 보내기 // 결혼한 사람들 보내기
for (itertype(m_Marriages) it = m_Marriages.begin(); it != m_Marriages.end(); ++it) for (itertype(m_Marriages) it = m_Marriages.begin(); it != m_Marriages.end(); ++it)
{ {
TMarriage* pMarriage = *it; TMarriage* pMarriage = *it;
@ -280,7 +280,7 @@ namespace marriage
} }
} }
// 결혼식 보내기 // 결혼식 보내기
for (itertype(m_mapRunningWedding) it = m_mapRunningWedding.begin(); it != m_mapRunningWedding.end(); ++it) for (itertype(m_mapRunningWedding) it = m_mapRunningWedding.begin(); it != m_mapRunningWedding.end(); ++it)
{ {
const TWedding& t = it->second; const TWedding& t = it->second;

View File

@ -233,7 +233,7 @@ bool CMonarch::SetMonarch(const char * name)
} }
delete pMsg; delete pMsg;
//db에 입력 //db에 입력
snprintf(szQuery, sizeof(szQuery), snprintf(szQuery, sizeof(szQuery),
"REPLACE INTO monarch (empire, name, windate, money) VALUES(%d, %d, now(), %ld)", Empire, p->pid[Empire], p->money[Empire]); "REPLACE INTO monarch (empire, name, windate, money) VALUES(%d, %d, now(), %ld)", Empire, p->pid[Empire], p->money[Empire]);

View File

@ -20,7 +20,7 @@ CPrivManager::~CPrivManager()
} }
// //
// @version 05/06/07 Bang2ni - 중복적으로 보너스가 적용 된 길드에 대한 처리 // @version 05/06/07 Bang2ni - 중복적으로 보너스가 적용 된 길드에 대한 처리
// //
void CPrivManager::Update() void CPrivManager::Update()
{ {
@ -37,8 +37,8 @@ void CPrivManager::Update()
typeof(m_aPrivGuild[p->type].begin()) it = m_aPrivGuild[p->type].find(p->guild_id); typeof(m_aPrivGuild[p->type].begin()) it = m_aPrivGuild[p->type].find(p->guild_id);
// ADD_GUILD_PRIV_TIME // ADD_GUILD_PRIV_TIME
// 길드에 중복적으로 보너스가 설정되었을 경우 map 의 value 가 갱신(수정) 되었으므로 // 길드에 중복적으로 보너스가 설정되었을 경우 map 의 value 가 갱신(수정) 되었으므로
// TPrivGuildData 의 포인터가 같을때 실제로 삭제해 주고 게임서버들에게 cast 해 준다. // TPrivGuildData 의 포인터가 같을때 실제로 삭제해 주고 게임서버들에게 cast 해 준다.
if (it != m_aPrivGuild[p->type].end() && it->second == p) { if (it != m_aPrivGuild[p->type].end() && it->second == p) {
m_aPrivGuild[p->type].erase(it); m_aPrivGuild[p->type].erase(it);
SendChangeGuildPriv(p->guild_id, p->type, 0, 0); SendChangeGuildPriv(p->guild_id, p->type, 0, 0);
@ -113,7 +113,7 @@ void CPrivManager::AddCharPriv(DWORD pid, BYTE type, int value)
} }
// //
// @version 05/06/07 Bang2ni - 이미 보너스가 적용 된 길드에 보너스 설정 // @version 05/06/07 Bang2ni - 이미 보너스가 적용 된 길드에 보너스 설정
// //
void CPrivManager::AddGuildPriv(DWORD guild_id, BYTE type, int value, time_t duration_sec) void CPrivManager::AddGuildPriv(DWORD guild_id, BYTE type, int value, time_t duration_sec)
{ {
@ -131,8 +131,8 @@ void CPrivManager::AddGuildPriv(DWORD guild_id, BYTE type, int value, time_t dur
m_pqPrivGuild.push(std::make_pair(end, p)); m_pqPrivGuild.push(std::make_pair(end, p));
// ADD_GUILD_PRIV_TIME // ADD_GUILD_PRIV_TIME
// 이미 보너스가 설정되 있다면 map 의 value 를 갱신해 준다. // 이미 보너스가 설정되 있다면 map 의 value 를 갱신해 준다.
// 이전 value 의 포인터는 priority queue 에서 삭제될 때 해제된다. // 이전 value 의 포인터는 priority queue 에서 삭제될 때 해제된다.
if (it != m_aPrivGuild[type].end()) if (it != m_aPrivGuild[type].end())
it->second = p; it->second = p;
else else
@ -158,8 +158,8 @@ void CPrivManager::AddEmpirePriv(BYTE empire, BYTE type, int value, time_t durat
time_t now = CClientManager::instance().GetCurrentTime(); time_t now = CClientManager::instance().GetCurrentTime();
time_t end = now+duration_sec; time_t end = now+duration_sec;
// 이전 설정값 무효화 // 이전 설정값 무효화
// priority_queue에 들어있는 pointer == m_aaPrivEmpire[type][empire] // priority_queue에 들어있는 pointer == m_aaPrivEmpire[type][empire]
{ {
if (m_aaPrivEmpire[type][empire]) if (m_aaPrivEmpire[type][empire])
m_aaPrivEmpire[type][empire]->bRemoved = true; m_aaPrivEmpire[type][empire]->bRemoved = true;
@ -177,7 +177,7 @@ void CPrivManager::AddEmpirePriv(BYTE empire, BYTE type, int value, time_t durat
} }
/** /**
* @version 05/06/08 Bang2ni - * @version 05/06/08 Bang2ni -
*/ */
struct FSendChangeGuildPriv struct FSendChangeGuildPriv
{ {

View File

@ -25,23 +25,23 @@ string trim(const string& str){return trim_left(trim_right(str));}
static string* StringSplit(string strOrigin, string strTok) static string* StringSplit(string strOrigin, string strTok)
{ {
int cutAt; //자르는위치 int cutAt; //자르는위치
int index = 0; //문자열인덱스 int index = 0; //문자열인덱스
string* strResult = new string[30]; //결과return 할변수 string* strResult = new string[30]; //결과return 할변수
//strTok을찾을때까지반복 //strTok을찾을때까지반복
while ((cutAt = strOrigin.find_first_of(strTok)) != strOrigin.npos) while ((cutAt = strOrigin.find_first_of(strTok)) != strOrigin.npos)
{ {
if (cutAt > 0) //자르는위치가0보다크면(성공시) if (cutAt > 0) //자르는위치가0보다크면(성공시)
{ {
strResult[index++] = strOrigin.substr(0, cutAt); //결과배열에추가 strResult[index++] = strOrigin.substr(0, cutAt); //결과배열에추가
} }
strOrigin = strOrigin.substr(cutAt+1); //원본은자른부분제외한나머지 strOrigin = strOrigin.substr(cutAt+1); //원본은자른부분제외한나머지
} }
if(strOrigin.length() > 0) //원본이아직남았으면 if(strOrigin.length() > 0) //원본이아직남았으면
{ {
strResult[index++] = strOrigin.substr(0, cutAt); //나머지를결과배열에추가 strResult[index++] = strOrigin.substr(0, cutAt); //나머지를결과배열에추가
} }
for( int i=0;i<index;i++) for( int i=0;i<index;i++)
@ -49,7 +49,7 @@ static string* StringSplit(string strOrigin, string strTok)
strResult[i] = trim(strResult[i]); strResult[i] = trim(strResult[i]);
} }
return strResult; //결과return return strResult; //결과return
} }
@ -60,25 +60,25 @@ int get_Item_Type_Value(string inputString)
"ITEM_ARMOR", "ITEM_USE", "ITEM_ARMOR", "ITEM_USE",
"ITEM_AUTOUSE", "ITEM_MATERIAL", "ITEM_AUTOUSE", "ITEM_MATERIAL",
"ITEM_SPECIAL", "ITEM_TOOL", "ITEM_SPECIAL", "ITEM_TOOL",
"ITEM_LOTTERY", "ITEM_ELK", //10개 "ITEM_LOTTERY", "ITEM_ELK", //10개
"ITEM_METIN", "ITEM_CONTAINER", "ITEM_METIN", "ITEM_CONTAINER",
"ITEM_FISH", "ITEM_ROD", "ITEM_FISH", "ITEM_ROD",
"ITEM_RESOURCE", "ITEM_CAMPFIRE", "ITEM_RESOURCE", "ITEM_CAMPFIRE",
"ITEM_UNIQUE", "ITEM_SKILLBOOK", "ITEM_UNIQUE", "ITEM_SKILLBOOK",
"ITEM_QUEST", "ITEM_POLYMORPH", //20개 "ITEM_QUEST", "ITEM_POLYMORPH", //20개
"ITEM_TREASURE_BOX", "ITEM_TREASURE_KEY", "ITEM_TREASURE_BOX", "ITEM_TREASURE_KEY",
"ITEM_SKILLFORGET", "ITEM_GIFTBOX", "ITEM_SKILLFORGET", "ITEM_GIFTBOX",
"ITEM_PICK", "ITEM_HAIR", "ITEM_PICK", "ITEM_HAIR",
"ITEM_TOTEM", "ITEM_BLEND", "ITEM_TOTEM", "ITEM_BLEND",
"ITEM_COSTUME", "ITEM_DS", //30개 "ITEM_COSTUME", "ITEM_DS", //30개
"ITEM_SPECIAL_DS", "ITEM_EXTRACT", "ITEM_SPECIAL_DS", "ITEM_EXTRACT",
"ITEM_SECONDARY_COIN", //33개 "ITEM_SECONDARY_COIN", //33개
"ITEM_RING", "ITEM_RING",
"ITEM_BELT", //35개 (EItemTypes 값으로 치면 34) "ITEM_BELT", //35개 (EItemTypes 값으로 치면 34)
}; };
@ -159,8 +159,8 @@ int get_Item_SubType_Value(int type_value, string inputString)
arSub29, //30 arSub29, //30
arSub31, //31 arSub31, //31
0, //32 0, //32
0, //33 반지 0, //33 반지
0, //34 벨트 0, //34 벨트
}; };
static int arNumberOfSubtype[_countof(arSubType)] = { static int arNumberOfSubtype[_countof(arSubType)] = {
0, 0,
@ -196,21 +196,21 @@ int get_Item_SubType_Value(int type_value, string inputString)
sizeof(arSub29)/sizeof(arSub29[0]), sizeof(arSub29)/sizeof(arSub29[0]),
sizeof(arSub31)/sizeof(arSub31[0]), sizeof(arSub31)/sizeof(arSub31[0]),
0, // 32 0, // 32
0, // 33 반지 0, // 33 반지
0, // 34 벨트 0, // 34 벨트
}; };
assert(_countof(arSubType) > type_value && "Subtype rule: Out of range!!"); assert(_countof(arSubType) > type_value && "Subtype rule: Out of range!!");
// assert 안 먹히는 듯.. // assert 안 먹히는 듯..
if (_countof(arSubType) <= type_value) if (_countof(arSubType) <= type_value)
{ {
SPDLOG_ERROR("SubType : Out of range!! (type_value: {}, count of registered subtype: {}", type_value, _countof(arSubType)); SPDLOG_ERROR("SubType : Out of range!! (type_value: {}, count of registered subtype: {}", type_value, _countof(arSubType));
return -1; return -1;
} }
//아이템 타입의 서브타입 어레이가 존재하는지 알아보고, 없으면 0 리턴 //아이템 타입의 서브타입 어레이가 존재하는지 알아보고, 없으면 0 리턴
if (arSubType[type_value]==0) { if (arSubType[type_value]==0) {
return 0; return 0;
} }
@ -246,13 +246,13 @@ int get_Item_AntiFlag_Value(string inputString)
int retValue = 0; int retValue = 0;
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열. string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arAntiFlag)/sizeof(arAntiFlag[0]);i++) { for(int i =0;i<sizeof(arAntiFlag)/sizeof(arAntiFlag[0]);i++) {
string tempString = arAntiFlag[i]; string tempString = arAntiFlag[i];
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩) for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
{ {
string tempString2 = arInputString[j]; string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //일치하는지 확인. if (tempString2.compare(tempString)==0) { //일치하는지 확인.
retValue = retValue + pow((float)2,(float)i); retValue = retValue + pow((float)2,(float)i);
} }
@ -275,13 +275,13 @@ int get_Item_Flag_Value(string inputString)
int retValue = 0; int retValue = 0;
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열. string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arFlag)/sizeof(arFlag[0]);i++) { for(int i =0;i<sizeof(arFlag)/sizeof(arFlag[0]);i++) {
string tempString = arFlag[i]; string tempString = arFlag[i];
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩) for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
{ {
string tempString2 = arInputString[j]; string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //일치하는지 확인. if (tempString2.compare(tempString)==0) { //일치하는지 확인.
retValue = retValue + pow((float)2,(float)i); retValue = retValue + pow((float)2,(float)i);
} }
@ -303,13 +303,13 @@ int get_Item_WearFlag_Value(string inputString)
int retValue = 0; int retValue = 0;
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열. string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arWearrFlag)/sizeof(arWearrFlag[0]);i++) { for(int i =0;i<sizeof(arWearrFlag)/sizeof(arWearrFlag[0]);i++) {
string tempString = arWearrFlag[i]; string tempString = arWearrFlag[i];
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩) for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
{ {
string tempString2 = arInputString[j]; string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //일치하는지 확인. if (tempString2.compare(tempString)==0) { //일치하는지 확인.
retValue = retValue + pow((float)2,(float)i); retValue = retValue + pow((float)2,(float)i);
} }
@ -329,13 +329,13 @@ int get_Item_Immune_Value(string inputString)
string arImmune[] = {"PARA","CURSE","STUN","SLEEP","SLOW","POISON","TERROR"}; string arImmune[] = {"PARA","CURSE","STUN","SLEEP","SLOW","POISON","TERROR"};
int retValue = 0; int retValue = 0;
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열. string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arImmune)/sizeof(arImmune[0]);i++) { for(int i =0;i<sizeof(arImmune)/sizeof(arImmune[0]);i++) {
string tempString = arImmune[i]; string tempString = arImmune[i];
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩) for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
{ {
string tempString2 = arInputString[j]; string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //일치하는지 확인. if (tempString2.compare(tempString)==0) { //일치하는지 확인.
retValue = retValue + pow((float)2,(float)i); retValue = retValue + pow((float)2,(float)i);
} }
@ -414,7 +414,7 @@ int get_Item_ApplyType_Value(string inputString)
} }
//몬스터 프로토도 읽는다. //몬스터 프로토도 읽는다.
int get_Mob_Rank_Value(string inputString) int get_Mob_Rank_Value(string inputString)
@ -508,13 +508,13 @@ int get_Mob_AIFlag_Value(string inputString)
int retValue = 0; int retValue = 0;
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열. string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arAIFlag)/sizeof(arAIFlag[0]);i++) { for(int i =0;i<sizeof(arAIFlag)/sizeof(arAIFlag[0]);i++) {
string tempString = arAIFlag[i]; string tempString = arAIFlag[i];
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩) for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
{ {
string tempString2 = arInputString[j]; string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //일치하는지 확인. if (tempString2.compare(tempString)==0) { //일치하는지 확인.
retValue = retValue + pow((float)2,(float)i); retValue = retValue + pow((float)2,(float)i);
} }
@ -533,13 +533,13 @@ int get_Mob_RaceFlag_Value(string inputString)
"ATT_ELEC","ATT_FIRE","ATT_ICE","ATT_WIND","ATT_EARTH","ATT_DARK"}; "ATT_ELEC","ATT_FIRE","ATT_ICE","ATT_WIND","ATT_EARTH","ATT_DARK"};
int retValue = 0; int retValue = 0;
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열. string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arRaceFlag)/sizeof(arRaceFlag[0]);i++) { for(int i =0;i<sizeof(arRaceFlag)/sizeof(arRaceFlag[0]);i++) {
string tempString = arRaceFlag[i]; string tempString = arRaceFlag[i];
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩) for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
{ {
string tempString2 = arInputString[j]; string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //일치하는지 확인. if (tempString2.compare(tempString)==0) { //일치하는지 확인.
retValue = retValue + pow((float)2,(float)i); retValue = retValue + pow((float)2,(float)i);
} }
@ -557,13 +557,13 @@ int get_Mob_ImmuneFlag_Value(string inputString)
string arImmuneFlag[] = {"STUN","SLOW","FALL","CURSE","POISON","TERROR", "REFLECT"}; string arImmuneFlag[] = {"STUN","SLOW","FALL","CURSE","POISON","TERROR", "REFLECT"};
int retValue = 0; int retValue = 0;
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열. string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arImmuneFlag)/sizeof(arImmuneFlag[0]);i++) { for(int i =0;i<sizeof(arImmuneFlag)/sizeof(arImmuneFlag[0]);i++) {
string tempString = arImmuneFlag[i]; string tempString = arImmuneFlag[i];
for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩) for (int j=0; j<30 ; j++) //최대 30개 단어까지. (하드코딩)
{ {
string tempString2 = arInputString[j]; string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //일치하는지 확인. if (tempString2.compare(tempString)==0) { //일치하는지 확인.
retValue = retValue + pow((float)2,(float)i); retValue = retValue + pow((float)2,(float)i);
} }
@ -581,14 +581,14 @@ int get_Mob_ImmuneFlag_Value(string inputString)
#ifndef __DUMP_PROTO__ #ifndef __DUMP_PROTO__
//몹 테이블을 셋팅해준다. //몹 테이블을 셋팅해준다.
bool Set_Proto_Mob_Table(TMobTable *mobTable, cCsvTable &csvTable,std::map<int,const char*> &nameMap) bool Set_Proto_Mob_Table(TMobTable *mobTable, cCsvTable &csvTable,std::map<int,const char*> &nameMap)
{ {
int col = 0; int col = 0;
str_to_number(mobTable->dwVnum, csvTable.AsStringByIndex(col++)); str_to_number(mobTable->dwVnum, csvTable.AsStringByIndex(col++));
strlcpy(mobTable->szName, csvTable.AsStringByIndex(col++), sizeof(mobTable->szName)); strlcpy(mobTable->szName, csvTable.AsStringByIndex(col++), sizeof(mobTable->szName));
//3. 지역별 이름 넣어주기. //3. 지역별 이름 넣어주기.
map<int,const char*>::iterator it; map<int,const char*>::iterator it;
it = nameMap.find(mobTable->dwVnum); it = nameMap.find(mobTable->dwVnum);
if (it != nameMap.end()) { if (it != nameMap.end()) {
@ -749,11 +749,11 @@ bool Set_Proto_Item_Table(TItemTable *itemTable, cCsvTable &csvTable,std::map<in
col = col + 1; col = col + 1;
} }
// vnum 및 vnum range 읽기. // vnum 및 vnum range 읽기.
{ {
std::string s(csvTable.AsStringByIndex(0)); std::string s(csvTable.AsStringByIndex(0));
int pos = s.find("~"); int pos = s.find("~");
// vnum 필드에 '~'가 없다면 패스 // vnum 필드에 '~'가 없다면 패스
if (std::string::npos == pos) if (std::string::npos == pos)
{ {
itemTable->dwVnum = dataArray[0]; itemTable->dwVnum = dataArray[0];
@ -777,7 +777,7 @@ bool Set_Proto_Item_Table(TItemTable *itemTable, cCsvTable &csvTable,std::map<in
} }
strlcpy(itemTable->szName, csvTable.AsStringByIndex(1), sizeof(itemTable->szName)); strlcpy(itemTable->szName, csvTable.AsStringByIndex(1), sizeof(itemTable->szName));
//지역별 이름 넣어주기. //지역별 이름 넣어주기.
map<int,const char*>::iterator it; map<int,const char*>::iterator it;
it = nameMap.find(itemTable->dwVnum); it = nameMap.find(itemTable->dwVnum);
if (it != nameMap.end()) { if (it != nameMap.end()) {

View File

@ -28,7 +28,7 @@ void CGrid::Clear()
int CGrid::FindBlank(int w, int h) int CGrid::FindBlank(int w, int h)
{ {
// 크기가 더 크다면 확인할 필요 없이 그냥 리턴 // 크기가 더 크다면 확인할 필요 없이 그냥 리턴
if (w > m_iWidth || h > m_iHeight) if (w > m_iWidth || h > m_iHeight)
return -1; return -1;
@ -86,7 +86,7 @@ bool CGrid::IsEmpty(int iPos, int w, int h)
{ {
int iRow = iPos / m_iWidth; int iRow = iPos / m_iWidth;
// Grid 안쪽인가를 먼저 검사 // Grid 안쪽인가를 먼저 검사
if (iRow + h > m_iHeight) if (iRow + h > m_iHeight)
return false; return false;