encoding #20

Merged
Exynox merged 22 commits from Tr0n/server:encoding into nightly 2024-04-07 08:59:38 +03:00
19 changed files with 490 additions and 488 deletions
Showing only changes of commit dd74eafc24 - Show all commits

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"; // 패왕
Review

This works for now, but we should check what this function does and if we can replace these strings as well with their English counterparts.

This works for now, but we should check what this function does and if we can replace these strings as well with their English counterparts.
Review

AFAIK it was only used in logging calls. The snippets were too short for any meaningful translation so I kept them the way they were.

AFAIK it was only used in logging calls. The snippets were too short for any meaningful translation so I kept them the way they were.
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;