fix db cpp encoding

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

View File

@ -135,7 +135,7 @@ void AuctionManager::LoadAuctionItem()
}
int rows;
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
{
return;
}
@ -182,7 +182,7 @@ void AuctionManager::LoadAuctionInfo()
}
int rows;
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
{
return;
}
@ -226,7 +226,7 @@ void AuctionManager::LoadSaleInfo()
}
int rows;
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
{
return;
}
@ -269,7 +269,7 @@ void AuctionManager::LoadWishInfo()
}
int rows;
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
{
return;
}
@ -311,7 +311,7 @@ void AuctionManager::LoadMyBidInfo ()
}
int rows;
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
{
return;
}
@ -518,7 +518,7 @@ AuctionResult AuctionManager::Impur(DWORD purchaser_id, const char* purchaser_na
return AUCTION_EXPIRED;
}
// 즉구 해버렸으므로, 경매는 끝났다.
// 즉구 해버렸으므로, 경매는 끝났다.
item_info->expired_time = 0;
item_info->bidder_id = purchaser_id;
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;
if (INADDR_NONE == in_address)
#endif
return true; // 아이피가 괴상하니 일단 블럭처리
return true; // 아이피가 괴상하니 일단 블럭처리
DO_ALL_BLOCK_IP(iter)
{

View File

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

View File

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

View File

@ -171,42 +171,42 @@ class FCompareVnum
bool CClientManager::InitializeMobTable()
{
//================== 함수 설명 ==================//
//1. 요약 : 'mob_proto.txt', 'mob_proto_test.txt', 'mob_names.txt' 파일을 읽고,
// (!)[mob_table] 테이블 오브젝트를 생성한다. (타입 : TMobTable)
//2. 순서
// 1) 'mob_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
// 2) 'mob_proto_test.txt'파일과 (a)[localMap] 맵으로
// (b)[test_map_mobTableByVnum](vnum:TMobTable) 맵을 생성한다.
// 3) 'mob_proto.txt' 파일과 (a)[localMap] 맵으로
// (!)[mob_table] 테이블을 만든다.
// <참고>
// 각 row 들 중,
// (b)[test_map_mobTableByVnum],(!)[mob_table] 모두에 있는 row는
// (b)[test_map_mobTableByVnum]의 것을 사용한다.
// 4) (b)[test_map_mobTableByVnum]의 row중, (!)[mob_table]에 없는 것을 추가한다.
//3. 테스트
// 1)'mob_proto.txt' 정보가 mob_table에 잘 들어갔는지. -> 완료
// 2)'mob_names.txt' 정보가 mob_table에 잘 들어갔는지.
// 3)'mob_proto_test.txt' 에서 [겹치는] 정보가 mob_table 에 잘 들어갔는지.
// 4)'mob_proto_test.txt' 에서 [새로운] 정보가 mob_table 에 잘 들어갔는지.
// 5) (최종) 게임 클라이언트에서 제대로 작동 하는지.
//================== 함수 설명 ==================//
//1. 요약 : 'mob_proto.txt', 'mob_proto_test.txt', 'mob_names.txt' 파일을 읽고,
// (!)[mob_table] 테이블 오브젝트를 생성한다. (타입 : TMobTable)
//2. 순서
// 1) 'mob_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
// 2) 'mob_proto_test.txt'파일과 (a)[localMap] 맵으로
// (b)[test_map_mobTableByVnum](vnum:TMobTable) 맵을 생성한다.
// 3) 'mob_proto.txt' 파일과 (a)[localMap] 맵으로
// (!)[mob_table] 테이블을 만든다.
// <참고>
// 각 row 들 중,
// (b)[test_map_mobTableByVnum],(!)[mob_table] 모두에 있는 row는
// (b)[test_map_mobTableByVnum]의 것을 사용한다.
// 4) (b)[test_map_mobTableByVnum]의 row중, (!)[mob_table]에 없는 것을 추가한다.
//3. 테스트
// 1)'mob_proto.txt' 정보가 mob_table에 잘 들어갔는지. -> 완료
// 2)'mob_names.txt' 정보가 mob_table에 잘 들어갔는지.
// 3)'mob_proto_test.txt' 에서 [겹치는] 정보가 mob_table 에 잘 들어갔는지.
// 4)'mob_proto_test.txt' 에서 [새로운] 정보가 mob_table 에 잘 들어갔는지.
// 5) (최종) 게임 클라이언트에서 제대로 작동 하는지.
//_______________________________________________//
//===============================================//
// 1) 'mob_names.txt' 파일을 읽어서 (a)[localMap] 맵을 만든다.
//<(a)localMap 맵 생성>
// 1) 'mob_names.txt' 파일을 읽어서 (a)[localMap] 맵을 만든다.
//<(a)localMap 맵 생성>
map<int,const char*> localMap;
bool isNameFile = true;
//<파일 읽기>
//<파일 읽기>
cCsvTable nameData;
if(!nameData.Load("mob_names.txt",'\t'))
{
SPDLOG_ERROR("mob_names.txt 파일을 읽어오지 못했습니다");
SPDLOG_ERROR("mob_names.txt 파일을 읽어오지 못했습니다");
isNameFile = false;
} else {
nameData.Next(); //설명row 생략.
nameData.Next(); //설명row 생략.
while(nameData.Next()) {
localMap[atoi(nameData.AsStringByIndex(0))] = nameData.AsStringByIndex(1);
}
@ -215,35 +215,35 @@ bool CClientManager::InitializeMobTable()
//===============================================//
// 2) 'mob_proto_test.txt'파일과 (a)localMap 맵으로
// (b)[test_map_mobTableByVnum](vnum:TMobTable) 맵을 생성한다.
// 2) 'mob_proto_test.txt'파일과 (a)localMap 맵으로
// (b)[test_map_mobTableByVnum](vnum:TMobTable) 맵을 생성한다.
//0.
set<int> vnumSet; //테스트용 파일 데이터중, 신규여부 확인에 사용.
//1. 파일 읽어오기
set<int> vnumSet; //테스트용 파일 데이터중, 신규여부 확인에 사용.
//1. 파일 읽어오기
bool isTestFile = true;
cCsvTable test_data;
if(!test_data.Load("mob_proto_test.txt",'\t'))
{
SPDLOG_ERROR("테스트 파일이 없습니다. 그대로 진행합니다.");
SPDLOG_ERROR("테스트 파일이 없습니다. 그대로 진행합니다.");
isTestFile = false;
}
//2. (c)[test_map_mobTableByVnum](vnum:TMobTable) 맵 생성.
//2. (c)[test_map_mobTableByVnum](vnum:TMobTable) 맵 생성.
map<DWORD, TMobTable *> test_map_mobTableByVnum;
if (isTestFile) {
test_data.Next(); //설명 로우 넘어가기.
test_data.Next(); //설명 로우 넘어가기.
//ㄱ. 테스트 몬스터 테이블 생성.
//ㄱ. 테스트 몬스터 테이블 생성.
TMobTable * test_mob_table = NULL;
int test_MobTableSize = test_data.m_File.GetRowCount()-1;
test_mob_table = new TMobTable[test_MobTableSize];
memset(test_mob_table, 0, sizeof(TMobTable) * test_MobTableSize);
//ㄴ. 테스트 몬스터 테이블에 값을 넣고, 맵에까지 넣기.
//ㄴ. 테스트 몬스터 테이블에 값을 넣고, 맵에까지 넣기.
while(test_data.Next()) {
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));
@ -254,22 +254,22 @@ bool CClientManager::InitializeMobTable()
}
// 3) 'mob_proto.txt' 파일과 (a)[localMap] 맵으로
// (!)[mob_table] 테이블을 만든다.
// <참고>
// 각 row 들 중,
// (b)[test_map_mobTableByVnum],(!)[mob_table] 모두에 있는 row는
// (b)[test_map_mobTableByVnum]의 것을 사용한다.
// 3) 'mob_proto.txt' 파일과 (a)[localMap] 맵으로
// (!)[mob_table] 테이블을 만든다.
// <참고>
// 각 row 들 중,
// (b)[test_map_mobTableByVnum],(!)[mob_table] 모두에 있는 row는
// (b)[test_map_mobTableByVnum]의 것을 사용한다.
//1. 파일 읽기.
//1. 파일 읽기.
cCsvTable data;
if(!data.Load("mob_proto.txt",'\t')) {
SPDLOG_ERROR("mob_proto.txt 파일을 읽어오지 못했습니다");
SPDLOG_ERROR("mob_proto.txt 파일을 읽어오지 못했습니다");
return false;
}
data.Next(); //설명 row 넘어가기
//2. (!)[mob_table] 생성하기
//2.1 새로 추가되는 갯수를 파악
data.Next(); //설명 row 넘어가기
//2. (!)[mob_table] 생성하기
//2.1 새로 추가되는 갯수를 파악
int addNumber = 0;
while(data.Next()) {
int vnum = atoi(data.AsStringByIndex(0));
@ -279,15 +279,15 @@ bool CClientManager::InitializeMobTable()
addNumber++;
}
}
//data를 다시 첫줄로 옮긴다.(다시 읽어온다;;)
//data를 다시 첫줄로 옮긴다.(다시 읽어온다;;)
data.Destroy();
if(!data.Load("mob_proto.txt",'\t'))
{
SPDLOG_ERROR("mob_proto.txt 파일을 읽어오지 못했습니다");
SPDLOG_ERROR("mob_proto.txt 파일을 읽어오지 못했습니다");
return false;
}
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
//2.2 크기에 맞게 mob_table 생성
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
//2.2 크기에 맞게 mob_table 생성
if (!m_vec_mobTable.empty())
{
SPDLOG_DEBUG("RELOAD: mob_proto");
@ -296,18 +296,18 @@ bool CClientManager::InitializeMobTable()
m_vec_mobTable.resize(data.m_File.GetRowCount()-1 + addNumber);
memset(&m_vec_mobTable[0], 0, sizeof(TMobTable) * m_vec_mobTable.size());
TMobTable * mob_table = &m_vec_mobTable[0];
//2.3 데이터 채우기
//2.3 데이터 채우기
while (data.Next())
{
int col = 0;
//(b)[test_map_mobTableByVnum]에 같은 row가 있는지 조사.
//(b)[test_map_mobTableByVnum]에 같은 row가 있는지 조사.
bool isSameRow = true;
std::map<DWORD, TMobTable *>::iterator it_map_mobTable;
it_map_mobTable = test_map_mobTableByVnum.find(atoi(data.AsStringByIndex(col)));
if(it_map_mobTable == test_map_mobTableByVnum.end()) {
isSameRow = false;
}
//같은 row 가 있으면 (b)에서 읽어온다.
//같은 row 가 있으면 (b)에서 읽어온다.
if(isSameRow) {
TMobTable *tempTable = it_map_mobTable->second;
@ -378,13 +378,13 @@ bool CClientManager::InitializeMobTable()
if (!Set_Proto_Mob_Table(mob_table, data, localMap))
{
SPDLOG_ERROR("몹 프로토 테이블 셋팅 실패.");
SPDLOG_ERROR("몹 프로토 테이블 셋팅 실패.");
}
}
//셋에 vnum 추가
//셋에 vnum 추가
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();
isTestFile = true;
test_data;
if(!test_data.Load("mob_proto_test.txt",'\t'))
{
SPDLOG_ERROR("테스트 파일이 없습니다. 그대로 진행합니다.");
SPDLOG_ERROR("테스트 파일이 없습니다. 그대로 진행합니다.");
isTestFile = false;
}
if(isTestFile) {
test_data.Next(); //설명 로우 넘어가기.
test_data.Next(); //설명 로우 넘어가기.
while (test_data.Next()) //테스트 데이터 각각을 훑어나가며,새로운 것을 추가한다.
while (test_data.Next()) //테스트 데이터 각각을 훑어나가며,새로운 것을 추가한다.
{
//중복되는 부분이면 넘어간다.
//중복되는 부분이면 넘어간다.
set<int>::iterator itVnum;
itVnum=vnumSet.find(atoi(test_data.AsStringByIndex(0)));
if (itVnum != vnumSet.end()) {
@ -419,7 +419,7 @@ bool CClientManager::InitializeMobTable()
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);
@ -447,8 +447,8 @@ bool CClientManager::InitializeShopTable()
std::unique_ptr<SQLMsg> pkMsg2(CDBManager::instance().DirectQuery(s_szQuery));
// shop의 vnum은 있는데 shop_item 이 없을경우... 실패로 처리되니 주의 요망.
// 고처야할부분
// shop의 vnum은 있는데 shop_item 이 없을경우... 실패로 처리되니 주의 요망.
// 고처야할부분
SQLResult * pRes2 = pkMsg2->Get();
if (!pRes2->uiNumRows)
@ -487,7 +487,7 @@ bool CClientManager::InitializeShopTable()
str_to_number(shop_table->dwNPCVnum, data[col++]);
if (!data[col]) // 아이템이 하나도 없으면 NULL이 리턴 되므로..
if (!data[col]) // 아이템이 하나도 없으면 NULL이 리턴 되므로..
continue;
TShopItemTable * pItem = &shop_table->items[shop_table->byItemCount];
@ -560,7 +560,7 @@ bool CClientManager::InitializeQuestItemTable()
continue;
}
tbl.bType = ITEM_QUEST; // quest_item_proto 테이블에 있는 것들은 모두 ITEM_QUEST 유형
tbl.bType = ITEM_QUEST; // quest_item_proto 테이블에 있는 것들은 모두 ITEM_QUEST 유형
tbl.bSize = 1;
m_vec_itemTable.push_back(tbl);
@ -571,39 +571,39 @@ bool CClientManager::InitializeQuestItemTable()
bool CClientManager::InitializeItemTable()
{
//================== 함수 설명 ==================//
//1. 요약 : 'item_proto.txt', 'item_proto_test.txt', 'item_names.txt' 파일을 읽고,
// <item_table>(TItemTable), <m_map_itemTableByVnum> 오브젝트를 생성한다.
//2. 순서
// 1) 'item_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
// 2) 'item_proto_text.txt'파일과 (a)[localMap] 맵으로
// (b)[test_map_itemTableByVnum](vnum:TItemTable) 맵을 생성한다.
// 3) 'item_proto.txt' 파일과 (a)[localMap] 맵으로
// (!)[item_table], <m_map_itemTableByVnum>을 만든다.
// <참고>
// 각 row 들 중,
// (b)[test_map_itemTableByVnum],(!)[mob_table] 모두에 있는 row는
// (b)[test_map_itemTableByVnum]의 것을 사용한다.
// 4) (b)[test_map_itemTableByVnum]의 row중, (!)[item_table]에 없는 것을 추가한다.
//3. 테스트
// 1)'item_proto.txt' 정보가 item_table에 잘 들어갔는지. -> 완료
// 2)'item_names.txt' 정보가 item_table에 잘 들어갔는지.
// 3)'item_proto_test.txt' 에서 [겹치는] 정보가 item_table 에 잘 들어갔는지.
// 4)'item_proto_test.txt' 에서 [새로운] 정보가 item_table 에 잘 들어갔는지.
// 5) (최종) 게임 클라이언트에서 제대로 작동 하는지.
//================== 함수 설명 ==================//
//1. 요약 : 'item_proto.txt', 'item_proto_test.txt', 'item_names.txt' 파일을 읽고,
// <item_table>(TItemTable), <m_map_itemTableByVnum> 오브젝트를 생성한다.
//2. 순서
// 1) 'item_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
// 2) 'item_proto_text.txt'파일과 (a)[localMap] 맵으로
// (b)[test_map_itemTableByVnum](vnum:TItemTable) 맵을 생성한다.
// 3) 'item_proto.txt' 파일과 (a)[localMap] 맵으로
// (!)[item_table], <m_map_itemTableByVnum>을 만든다.
// <참고>
// 각 row 들 중,
// (b)[test_map_itemTableByVnum],(!)[mob_table] 모두에 있는 row는
// (b)[test_map_itemTableByVnum]의 것을 사용한다.
// 4) (b)[test_map_itemTableByVnum]의 row중, (!)[item_table]에 없는 것을 추가한다.
//3. 테스트
// 1)'item_proto.txt' 정보가 item_table에 잘 들어갔는지. -> 완료
// 2)'item_names.txt' 정보가 item_table에 잘 들어갔는지.
// 3)'item_proto_test.txt' 에서 [겹치는] 정보가 item_table 에 잘 들어갔는지.
// 4)'item_proto_test.txt' 에서 [새로운] 정보가 item_table 에 잘 들어갔는지.
// 5) (최종) 게임 클라이언트에서 제대로 작동 하는지.
//_______________________________________________//
//=================================================================================//
// 1) 'item_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
// 1) 'item_names.txt' 파일을 읽어서 (a)[localMap](vnum:name) 맵을 만든다.
//=================================================================================//
bool isNameFile = true;
map<int,const char*> localMap;
cCsvTable nameData;
if(!nameData.Load("item_names.txt",'\t'))
{
SPDLOG_ERROR("item_names.txt 파일을 읽어오지 못했습니다");
SPDLOG_ERROR("item_names.txt 파일을 읽어오지 못했습니다");
isNameFile = false;
} else {
nameData.Next();
@ -614,32 +614,32 @@ bool CClientManager::InitializeItemTable()
//_________________________________________________________________//
//=================================================================//
// 2) 'item_proto_text.txt'파일과 (a)[localMap] 맵으로
// (b)[test_map_itemTableByVnum](vnum:TItemTable) 맵을 생성한다.
// 2) 'item_proto_text.txt'파일과 (a)[localMap] 맵으로
// (b)[test_map_itemTableByVnum](vnum:TItemTable) 맵을 생성한다.
//=================================================================//
map<DWORD, TItemTable *> test_map_itemTableByVnum;
//1. 파일 읽어오기.
//1. 파일 읽어오기.
cCsvTable test_data;
if(!test_data.Load("item_proto_test.txt",'\t'))
{
SPDLOG_ERROR("item_proto_test.txt 파일을 읽어오지 못했습니다");
SPDLOG_ERROR("item_proto_test.txt 파일을 읽어오지 못했습니다");
//return false;
} else {
test_data.Next(); //설명 로우 넘어가기.
test_data.Next(); //설명 로우 넘어가기.
//2. 테스트 아이템 테이블 생성.
//2. 테스트 아이템 테이블 생성.
TItemTable * test_item_table = NULL;
int test_itemTableSize = test_data.m_File.GetRowCount()-1;
test_item_table = new TItemTable[test_itemTableSize];
memset(test_item_table, 0, sizeof(TItemTable) * test_itemTableSize);
//3. 테스트 아이템 테이블에 값을 넣고, 맵에까지 넣기.
//3. 테스트 아이템 테이블에 값을 넣고, 맵에까지 넣기.
while(test_data.Next()) {
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));
@ -651,25 +651,25 @@ bool CClientManager::InitializeItemTable()
//========================================================================//
// 3) 'item_proto.txt' 파일과 (a)[localMap] 맵으로
// (!)[item_table], <m_map_itemTableByVnum>을 만든다.
// <참고>
// 각 row 들 중,
// (b)[test_map_itemTableByVnum],(!)[mob_table] 모두에 있는 row는
// (b)[test_map_itemTableByVnum]의 것을 사용한다.
// 3) 'item_proto.txt' 파일과 (a)[localMap] 맵으로
// (!)[item_table], <m_map_itemTableByVnum>을 만든다.
// <참고>
// 각 row 들 중,
// (b)[test_map_itemTableByVnum],(!)[mob_table] 모두에 있는 row는
// (b)[test_map_itemTableByVnum]의 것을 사용한다.
//========================================================================//
//vnum들을 저장할 셋. 새로운 테스트 아이템을 판별할때 사용된다.
//vnum들을 저장할 셋. 새로운 테스트 아이템을 판별할때 사용된다.
set<int> vnumSet;
//파일 읽어오기.
//파일 읽어오기.
cCsvTable data;
if(!data.Load("item_proto.txt",'\t'))
{
SPDLOG_ERROR("item_proto.txt 파일을 읽어오지 못했습니다");
SPDLOG_ERROR("item_proto.txt 파일을 읽어오지 못했습니다");
return false;
}
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
if (!m_vec_itemTable.empty())
{
@ -678,8 +678,8 @@ bool CClientManager::InitializeItemTable()
m_map_itemTableByVnum.clear();
}
//===== 아이템 테이블 생성 =====//
//새로 추가되는 갯수를 파악한다.
//===== 아이템 테이블 생성 =====//
//새로 추가되는 갯수를 파악한다.
int addNumber = 0;
while(data.Next()) {
int vnum = atoi(data.AsStringByIndex(0));
@ -689,14 +689,14 @@ bool CClientManager::InitializeItemTable()
addNumber++;
}
}
//data를 다시 첫줄로 옮긴다.(다시 읽어온다;;)
//data를 다시 첫줄로 옮긴다.(다시 읽어온다;;)
data.Destroy();
if(!data.Load("item_proto.txt",'\t'))
{
SPDLOG_ERROR("item_proto.txt 파일을 읽어오지 못했습니다");
SPDLOG_ERROR("item_proto.txt 파일을 읽어오지 못했습니다");
return false;
}
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
data.Next(); //맨 윗줄 제외 (아이템 칼럼을 설명하는 부분)
m_vec_itemTable.resize(data.m_File.GetRowCount() - 1 + addNumber);
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;
it_map_itemTable = test_map_itemTableByVnum.find(atoi(data.AsStringByIndex(col)));
if(it_map_itemTable == test_map_itemTableByVnum.end()) {
//각 칼럼 데이터 저장
//각 칼럼 데이터 저장
if (!Set_Proto_Item_Table(item_table, data, localMap))
{
SPDLOG_ERROR("아이템 프로토 테이블 셋팅 실패.");
SPDLOG_ERROR("아이템 프로토 테이블 셋팅 실패.");
}
} else { //$$$$$$$$$$$$$$$$$$$$$$$ 테스트 아이템 정보가 있다!
} else { //$$$$$$$$$$$$$$$$$$$$$$$ 테스트 아이템 정보가 있다!
TItemTable *tempTable = it_map_itemTable->second;
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();
if(!test_data.Load("item_proto_test.txt",'\t'))
{
SPDLOG_ERROR("item_proto_test.txt 파일을 읽어오지 못했습니다");
SPDLOG_ERROR("item_proto_test.txt 파일을 읽어오지 못했습니다");
//return false;
} else {
test_data.Next(); //설명 로우 넘어가기.
test_data.Next(); //설명 로우 넘어가기.
while (test_data.Next()) //테스트 데이터 각각을 훑어나가며,새로운 것을 추가한다.
while (test_data.Next()) //테스트 데이터 각각을 훑어나가며,새로운 것을 추가한다.
{
//중복되는 부분이면 넘어간다.
//중복되는 부분이면 넘어간다.
set<int>::iterator itVnum;
itVnum=vnumSet.find(atoi(test_data.AsStringByIndex(0)));
if (itVnum != vnumSet.end()) {
@ -798,7 +798,7 @@ bool CClientManager::InitializeItemTable()
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)
{
case 0 :
return "패왕";
return "\xEF\xBF\xBD\xD0\xBF\xEF\xBF\xBD"; // 패왕
case 1 :
return "맹장";
return "\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD"; // 맹장
case 2 :
return "수호";
return "\xEF\xBF\xBD\xEF\xBF\xBD\xC8\xA3"; // 수호
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:
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)
SPDLOG_DEBUG("GuildWar: GUILD_WAR_RESERVE type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
@ -173,21 +173,21 @@ void CClientManager::GuildWar(CPeer* peer, TPacketGuildWar* p)
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);
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().StartWar(p->bType, p->dwGuildFrom, p->dwGuildTo);
break;
case GUILD_WAR_OVER: // 길드전 정상 종료
case GUILD_WAR_OVER: // 길드전 정상 종료
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);
break;
case GUILD_WAR_END: // 길드전 비정상 종료
case GUILD_WAR_END: // 길드전 비정상 종료
SPDLOG_DEBUG("GuildWar: GUILD_WAR_END type({}) guild({} - {})", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().RecvWarEnd(p->dwGuildFrom, p->dwGuildTo);
return; // NOTE: RecvWarEnd에서 패킷을 보내므로 따로 브로드캐스팅 하지 않는다.
return; // NOTE: RecvWarEnd에서 패킷을 보내므로 따로 브로드캐스팅 하지 않는다.
case GUILD_WAR_CANCEL :
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;
memset(pkTab, 0, sizeof(TAccountTable));
// 첫번째 컬럼 것만 참고 한다 (JOIN QUERY를 위한 것 임)
// 첫번째 컬럼 것만 참고 한다 (JOIN QUERY를 위한 것 임)
strlcpy(input_pwd, row[col++], sizeof(input_pwd));
str_to_number(pkTab->id, row[col++]);
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 (msg->Get()->uiNumRows == 0)
{
SPDLOG_DEBUG("RESULT_LOGIN: no account");
@ -396,14 +396,14 @@ void CClientManager::RESULT_LOGIN(CPeer * peer, SQLMsg * msg)
}
else
{
if (!info->pAccountTable) // 이럴리는 없겠지만;;
if (!info->pAccountTable) // 이럴리는 없겠지만;;
{
peer->EncodeReturn(HEADER_DG_LOGIN_WRONG_PASSWD, info->dwHandle);
delete info;
return;
}
// 다른 컨넥션이 이미 로그인 해버렸다면.. 이미 접속했다고 보내야 한다.
// 다른 컨넥션이 이미 로그인 해버렸다면.. 이미 접속했다고 보내야 한다.
if (!InsertLogonAccount(info->pAccountTable->login, peer->GetHandle(), info->ip))
{
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;
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
if ((rows = mysql_num_rows(res)) <= 0) // 데이터 없음
{
pVec->clear();
return true;
@ -158,7 +158,7 @@ size_t CreatePlayerSaveQuery(char * pszQuery, size_t querySize, TPlayerTable * p
pkTab->horse.sStamina,
pkTab->horse_skill_point);
// Binary 로 바꾸기 위한 임시 공간
// Binary 로 바꾸기 위한 임시 공간
char text[8192 + 1];
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;
//
// 한 계정에 속한 모든 캐릭터들 캐쉬처리
// 한 계정에 속한 모든 캐릭터들 캐쉬처리
//
CLoginData * pLoginData = GetLoginDataByAID(packet->account_id);
@ -222,12 +222,12 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
}
//----------------------------------------------------------------
// 1. 유저정보가 DBCache 에 존재 : DBCache에서
// 2. 유저정보가 DBCache 에 없음 : DB에서
// 1. 유저정보가 DBCache 에 존재 : DBCache에서
// 2. 유저정보가 DBCache 에 없음 : DB에서
// ---------------------------------------------------------------
//----------------------------------
// 1. 유저정보가 DBCache 에 존재 : DBCache에서
// 1. 유저정보가 DBCache 에 존재 : DBCache에서
//----------------------------------
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);
//--------------------------------------------
// 아이템 & AFFECT & QUEST 로딩 :
// 아이템 & AFFECT & QUEST 로딩 :
//--------------------------------------------
// 1) 아이템이 DBCache 에 존재 : DBCache 에서 가져옴
// 2) 아이템이 DBCache 에 없음 : DB 에서 가져옴
// 1) 아이템이 DBCache 에 존재 : DBCache 에서 가져옴
// 2) 아이템이 DBCache 에 없음 : DB 에서 가져옴
/////////////////////////////////////////////
// 1) 아이템이 DBCache 에 존재 : DBCache 에서 가져옴
// 1) 아이템이 DBCache 에 존재 : DBCache 에서 가져옴
/////////////////////////////////////////////
if (pSet)
{
@ -288,7 +288,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
CItemCache * c = *it++;
TPlayerItem * p = c->Get();
if (p->vnum) // vnum이 없으면 삭제된 아이템이다.
if (p->vnum) // vnum이 없으면 삭제된 아이템이다.
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));
}
/////////////////////////////////////////////
// 2) 아이템이 DBCache 에 없음 : DB 에서 가져옴
// 2) 아이템이 DBCache 에 없음 : DB 에서 가져옴
/////////////////////////////////////////////
else
{
@ -348,7 +348,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
//return;
}
//----------------------------------
// 2. 유저정보가 DBCache 에 없음 : DB에서
// 2. 유저정보가 DBCache 에 없음 : DB에서
//----------------------------------
else
{
@ -357,7 +357,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
char queryStr[QUERY_MAX_LEN];
//--------------------------------------------------------------
// 캐릭터 정보 얻어오기 : 무조건 DB에서
// 캐릭터 정보 얻어오기 : 무조건 DB에서
//--------------------------------------------------------------
snprintf(queryStr, sizeof(queryStr),
"SELECT "
@ -373,7 +373,7 @@ void CClientManager::QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoad
CDBManager::instance().ReturnQuery(queryStr, QID_PLAYER, peer->GetHandle(), pkInfo);
//--------------------------------------------------------------
// 아이템 가져오기
// 아이템 가져오기
//--------------------------------------------------------------
snprintf(queryStr, sizeof(queryStr),
"SELECT id,window+0,pos,count,vnum,socket0,socket1,socket2,attrtype0,attrvalue0,attrtype1,attrvalue1,attrtype2,attrvalue2,attrtype3,attrvalue3,attrtype4,attrvalue4,attrtype5,attrvalue5,attrtype6,attrvalue6 "
@ -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));
//--------------------------------------------------------------
// QUEST 가져오기
// QUEST 가져오기
//--------------------------------------------------------------
snprintf(queryStr, sizeof(queryStr),
"SELECT dwPID,szName,szState,lValue FROM quest%s WHERE dwPID=%d",
GetTablePostfix(), packet->player_id);
CDBManager::instance().ReturnQuery(queryStr, QID_QUEST, peer->GetHandle(), new ClientHandleInfo(dwHandle, packet->player_id,packet->account_id));
//독일 선물 기능에서 item_award테이블에서 login 정보를 얻기위해 account id도 넘겨준다
//독일 선물 기능에서 item_award테이블에서 login 정보를 얻기위해 account id도 넘겨준다
//--------------------------------------------------------------
// AFFECT 가져오기
// AFFECT 가져오기
//--------------------------------------------------------------
snprintf(queryStr, sizeof(queryStr),
"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);
if(pSet == NULL)
return;
typeof(pSet->begin()) it = pSet->begin(); //taken_time이 NULL인것들 읽어옴
typeof(pSet->begin()) it = pSet->begin(); //taken_time이 NULL인것들 읽어옴
while(it != pSet->end() )
{
TItemAward * pItemAward = *(it++);
char* whyStr = pItemAward->szWhy; //why 콜룸 읽기
char cmdStr[100] = ""; //why콜룸에서 읽은 값을 임시 문자열에 복사해둠
strcpy(cmdStr,whyStr); //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문
char* whyStr = pItemAward->szWhy; //why 콜룸 읽기
char cmdStr[100] = ""; //why콜룸에서 읽은 값을 임시 문자열에 복사해둠
strcpy(cmdStr,whyStr); //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문
char command[20] = "";
strcpy(command,GetCommand(cmdStr).c_str()); // command 얻기
if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면
strcpy(command,GetCommand(cmdStr).c_str()); // command 얻기
if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면
{
TPacketItemAwardInfromer giftData;
strcpy(giftData.login, pItemAward->szLogin); //로그인 아이디 복사
strcpy(giftData.command, command); //명령어 복사
giftData.vnum = pItemAward->dwVnum; //아이템 vnum도 복사
strcpy(giftData.login, pItemAward->szLogin); //로그인 아이디 복사
strcpy(giftData.command, command); //명령어 복사
giftData.vnum = pItemAward->dwVnum; //아이템 vnum도 복사
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)
{
if (mysql_num_rows(res) == 0) // 데이터 없음
if (mysql_num_rows(res) == 0) // 데이터 없음
return false;
memset(pkTab, 0, sizeof(TPlayerTable));
@ -529,11 +529,11 @@ bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab)
int max_point = pkTab->level - 9;
int skill_point =
std::min<int>(20, pkTab->skills[121].bLevel) + // SKILL_LEADERSHIP 통솔력
std::min<int>(20, pkTab->skills[124].bLevel) + // SKILL_MINING 채광
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[142].bLevel); // SKILL_RESIST_PENETRATE 관통저항
std::min<int>(20, pkTab->skills[121].bLevel) + // SKILL_LEADERSHIP 통솔력
std::min<int>(20, pkTab->skills[124].bLevel) + // SKILL_MINING 채광
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[142].bLevel); // SKILL_RESIST_PENETRATE 관통저항
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);
RESULT_QUEST_LOAD(peer, pSQLResult, info->dwHandle, info->player_id);
//aid얻기
//aid얻기
ClientHandleInfo* temp1 = info.get();
if (temp1 == NULL)
break;
CLoginData* pLoginData1 = GetLoginDataByAID(temp1->account_id); //
//독일 선물 기능
//독일 선물 기능
if( pLoginData1->GetAccountRef().login == NULL)
break;
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)
{
static std::vector<TPlayerItem> s_items;
//DB에서 아이템 정보를 읽어온다.
//DB에서 아이템 정보를 읽어온다.
CreateItemTableFromRes(pRes, &s_items, dwPID);
DWORD dwCount = s_items.size();
peer->EncodeHeader(HEADER_DG_ITEM_LOAD, dwHandle, sizeof(DWORD) + sizeof(TPlayerItem) * dwCount);
peer->EncodeDWORD(dwCount);
//CacheSet을 만든다
//CacheSet을 만든다
CreateItemCacheSet(dwPID);
// 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);
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;
if ((iNumRows = mysql_num_rows(pRes)) == 0) // 데이터 없음
if ((iNumRows = mysql_num_rows(pRes)) == 0) // 데이터 없음
return;
static std::vector<TPacketAffectElement> s_elements;
@ -793,7 +793,7 @@ void CClientManager::__QUERY_PLAYER_CREATE(CPeer *peer, DWORD dwHandle, TPlayerC
int queryLen;
DWORD player_id;
// 한 계정에 X초 내로 캐릭터 생성을 할 수 없다.
// 한 계정에 X초 내로 캐릭터 생성을 할 수 없다.
auto it = s_createTimeByAccountID.find(packet->account_id);
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)
{
@ -1073,14 +1073,14 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
return;
}
// 삭제 성공
// 삭제 성공
SPDLOG_DEBUG("PLAYER_DELETE SUCCESS {}", dwPID);
char account_index_string[16];
snprintf(account_index_string, sizeof(account_index_string), "player_id%d", m_iPlayerIDStart + pi->account_index);
// 플레이어 테이블을 캐쉬에서 삭제한다.
// 플레이어 테이블을 캐쉬에서 삭제한다.
CPlayerTableCache * pkPlayerCache = GetPlayerCache(pi->player_id);
if (pkPlayerCache)
@ -1089,7 +1089,7 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
delete pkPlayerCache;
}
// 아이템들을 캐쉬에서 삭제한다.
// 아이템들을 캐쉬에서 삭제한다.
TItemCacheSet * pSet = GetItemCacheSet(pi->player_id);
if (pSet)
@ -1152,7 +1152,7 @@ void CClientManager::__RESULT_PLAYER_DELETE(CPeer *peer, SQLMsg* msg)
}
else
{
// 삭제 실패
// 삭제 실패
SPDLOG_DEBUG("PLAYER_DELETE FAIL NO ROW");
peer->EncodeHeader(HEADER_DG_PLAYER_DELETE_FAILED, pi->dwHandle, 1);
peer->EncodeBYTE(pi->account_index);
@ -1237,7 +1237,7 @@ void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg)
if (res->uiNumRows == 0)
{
// 새로운 하이스코어를 삽입
// 새로운 하이스코어를 삽입
char buf[256];
snprintf(buf, sizeof(buf), "INSERT INTO highscore%s VALUES('%s', %u, %d)", GetTablePostfix(), szBoard, pi->player_id, value);
CDBManager::instance().AsyncQuery(buf);
@ -1272,7 +1272,7 @@ void CClientManager::RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg)
CDBManager::instance().AsyncQuery(buf);
}
}
// TODO: 이곳에서 하이스코어가 업데이트 되었는지 체크하여 공지를 뿌려야한다.
// TODO: 이곳에서 하이스코어가 업데이트 되었는지 체크하여 공지를 뿌려야한다.
delete pi;
}
@ -1280,10 +1280,10 @@ void CClientManager::InsertLogoutPlayer(DWORD pid)
{
TLogoutPlayerMap::iterator it = m_map_logout.find(pid);
// 존재하지 않을경우 추가
// 존재하지 않을경우 추가
if (it != m_map_logout.end())
{
// 존재할경우 시간만 갱신
// 존재할경우 시간만 갱신
SPDLOG_TRACE("LOGOUT: Update player time pid({})", pid);
it->second->time = time(0);

View File

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

View File

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

View File

@ -242,7 +242,7 @@ void CGuildManager::ResultRanking(MYSQL_RES * pRes)
void CGuildManager::Update()
{
ProcessReserveWar(); // 예약 전쟁 처리
ProcessReserveWar(); // 예약 전쟁 처리
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)
{
@ -493,7 +493,7 @@ void CGuildManager::WarEnd(DWORD GID1, DWORD GID2, bool bForceDraw)
bool bDraw = false;
if (!bForceDraw) // 강제 무승부가 아닐 경우에는 점수를 체크한다.
if (!bForceDraw) // 강제 무승부가 아닐 경우에는 점수를 체크한다.
{
if (pData->iScore[0] > pData->iScore[1])
{
@ -508,7 +508,7 @@ void CGuildManager::WarEnd(DWORD GID1, DWORD GID2, bool bForceDraw)
else
bDraw = true;
}
else // 강제 무승부일 경우에는 무조건 무승부
else // 강제 무승부일 경우에는 무조건 무승부
bDraw = true;
if (bDraw)
@ -516,14 +516,14 @@ void CGuildManager::WarEnd(DWORD GID1, DWORD GID2, bool bForceDraw)
else
ProcessWinLose(win_guild, lose_guild);
// DB 서버에서 자체적으로 끝낼 때도 있기 때문에 따로 패킷을 보내줘야 한다.
// DB 서버에서 자체적으로 끝낼 때도 있기 때문에 따로 패킷을 보내줘야 한다.
CClientManager::instance().for_each_peer(FSendPeerWar(0, GUILD_WAR_END, GID1, GID2));
RemoveWar(GID1, GID2);
}
//
// 길드전 정상 종료
// 길드전 정상 종료
//
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)
{
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)
@ -745,7 +745,7 @@ void CGuildManager::ChangeLadderPoint(DWORD GID, int change)
SPDLOG_DEBUG("GuildManager::ChangeLadderPoint {} {}", GID, r.ladder_point);
SPDLOG_DEBUG("{}", buf);
// Packet 보내기
// Packet 보내기
TPacketGuildLadder p;
p.dwGuild = GID;
@ -808,7 +808,7 @@ void CGuildManager::WithdrawMoney(CPeer* peer, DWORD dwGuild, INT iGold)
return;
}
// 돈이있으니 출금하고 올려준다
// 돈이있으니 출금하고 올려준다
if (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] =
{
@ -869,7 +869,7 @@ const int c_aiScoreByLevel[GUILD_MAX_LEVEL+1] =
const int c_aiScoreByRanking[GUILD_RANK_MAX_NUM+1] =
{
0,
55000, // 1위
55000, // 1위
50000,
45000,
40000,
@ -878,7 +878,7 @@ const int c_aiScoreByRanking[GUILD_RANK_MAX_NUM+1] =
28000,
24000,
21000,
18000, // 10위
18000, // 10위
15000,
12000,
10000,
@ -888,7 +888,7 @@ const int c_aiScoreByRanking[GUILD_RANK_MAX_NUM+1] =
3000,
2000,
1000,
500 // 20위
500 // 20위
};
void CGuildManager::BootReserveWar()
@ -932,8 +932,8 @@ void CGuildManager::BootReserveWar()
char buf[512];
snprintf(buf, sizeof(buf), "GuildWar: BootReserveWar : step %d id %u GID1 %u GID2 %u", i, t.dwID, t.dwGuildFrom, t.dwGuildTo);
// i == 0 이면 길드전 도중 DB가 튕긴 것이므로 무승부 처리한다.
// 또는, 5분 이하 남은 예약 길드전도 무승부 처리한다. (각자의 배팅액을 돌려준다)
// i == 0 이면 길드전 도중 DB가 튕긴 것이므로 무승부 처리한다.
// 또는, 5분 이하 남은 예약 길드전도 무승부 처리한다. (각자의 배팅액을 돌려준다)
//if (i == 0 || (int) t.dwTime - CClientManager::instance().GetCurrentTime() < 60 * 5)
if (i == 0 || (int) t.dwTime - CClientManager::instance().GetCurrentTime() < 0)
{
@ -1010,7 +1010,7 @@ bool CGuildManager::ReserveWar(TPacketGuildWar * p)
int lvp, rkp, alv, mc;
// 파워 계산
// 파워 계산
TGuild & k1 = TouchGuild(GID1);
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();
SPDLOG_DEBUG("GuildWar: {} lvp {} rkp {} alv {} mc {} power {}", GID1, lvp, rkp, alv, mc, t.lPowerFrom);
// 파워 계산
// 파워 계산
TGuild & k2 = TouchGuild(GID2);
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();
SPDLOG_DEBUG("GuildWar: {} lvp {} rkp {} alv {} mc {} power {}", GID2, lvp, rkp, alv, mc, t.lPowerTo);
// 핸디캡 계산
// 핸디캡 계산
if (t.lPowerTo > t.lPowerFrom)
{
polyHandicap.SetVar("pA", t.lPowerTo);
@ -1057,7 +1057,7 @@ bool CGuildManager::ReserveWar(TPacketGuildWar * p)
t.lHandicap = (int) polyHandicap.Eval();
SPDLOG_DEBUG("GuildWar: handicap {}", t.lHandicap);
// 쿼리
// 쿼리
char szQuery[512];
snprintf(szQuery, sizeof(szQuery),
@ -1094,7 +1094,7 @@ void CGuildManager::ProcessReserveWar()
CGuildWarReserve * pk = it2->second;
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);
@ -1135,9 +1135,11 @@ void CGuildManager::ProcessReserveWar()
pk->SetLastNoticeMin(iMin);
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"))
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)
{
if (m_data.bStarted) // 이미 시작된 것은 보내지 않는다.
if (m_data.bStarted) // 이미 시작된 것은 보내지 않는다.
return;
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()
{
@ -1458,7 +1460,7 @@ void CGuildWarReserve::End(int iScoreFrom, int iScoreTo)
double ratio = (double) it->second.second / dwWinnerBet;
// 10% 세금 공제 후 분배
// 10% 세금 공제 후 분배
SPDLOG_DEBUG("WAR_REWARD: {} {} ratio {}", it->first.c_str(), it->second.second, ratio);
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)
{
@ -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)
{

View File

@ -54,19 +54,19 @@ void ItemAwardManager::Load(SQLMsg * pMsg)
if (row[col])
{
strlcpy(kData->szWhy, row[col], sizeof(kData->szWhy));
//게임 중에 why콜룸에 변동이 생기면
char* whyStr = kData->szWhy; //why 콜룸 읽기
char cmdStr[100] = ""; //why콜룸에서 읽은 값을 임시 문자열에 복사해둠
strcpy(cmdStr,whyStr); //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문
//게임 중에 why콜룸에 변동이 생기면
char* whyStr = kData->szWhy; //why 콜룸 읽기
char cmdStr[100] = ""; //why콜룸에서 읽은 값을 임시 문자열에 복사해둠
strcpy(cmdStr,whyStr); //명령어 얻는 과정에서 토큰쓰면 원본도 토큰화 되기 때문
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);
if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면
if( !(strcmp(command,"GIFT") )) // command 가 GIFT이면
{
TPacketItemAwardInfromer giftData;
strcpy(giftData.login, kData->szLogin); //로그인 아이디 복사
strcpy(giftData.command, command); //명령어 복사
giftData.vnum = kData->dwVnum; //아이템 vnum도 복사
strcpy(giftData.login, kData->szLogin); //로그인 아이디 복사
strcpy(giftData.command, command); //명령어 복사
giftData.vnum = kData->dwVnum; //아이템 vnum도 복사
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_test_server = false;
//단위 초
//단위 초
int g_iPlayerCacheFlushSeconds = 60*7;
int g_iItemCacheFlushSeconds = 60*5;
//g_iLogoutSeconds 수치는 g_iPlayerCacheFlushSeconds 와 g_iItemCacheFlushSeconds 보다 길어야 한다.
//g_iLogoutSeconds 수치는 g_iPlayerCacheFlushSeconds 와 g_iItemCacheFlushSeconds 보다 길어야 한다.
int g_iLogoutSeconds = 60*10;
@ -122,13 +122,13 @@ int main()
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()
{

View File

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

View File

@ -233,7 +233,7 @@ bool CMonarch::SetMonarch(const char * name)
}
delete pMsg;
//db에 입력
//db에 입력
snprintf(szQuery, sizeof(szQuery),
"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()
{
@ -37,8 +37,8 @@ void CPrivManager::Update()
typeof(m_aPrivGuild[p->type].begin()) it = m_aPrivGuild[p->type].find(p->guild_id);
// ADD_GUILD_PRIV_TIME
// 길드에 중복적으로 보너스가 설정되었을 경우 map 의 value 가 갱신(수정) 되었으므로
// TPrivGuildData 의 포인터가 같을때 실제로 삭제해 주고 게임서버들에게 cast 해 준다.
// 길드에 중복적으로 보너스가 설정되었을 경우 map 의 value 가 갱신(수정) 되었으므로
// TPrivGuildData 의 포인터가 같을때 실제로 삭제해 주고 게임서버들에게 cast 해 준다.
if (it != m_aPrivGuild[p->type].end() && it->second == p) {
m_aPrivGuild[p->type].erase(it);
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)
{
@ -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));
// ADD_GUILD_PRIV_TIME
// 이미 보너스가 설정되 있다면 map 의 value 를 갱신해 준다.
// 이전 value 의 포인터는 priority queue 에서 삭제될 때 해제된다.
// 이미 보너스가 설정되 있다면 map 의 value 를 갱신해 준다.
// 이전 value 의 포인터는 priority queue 에서 삭제될 때 해제된다.
if (it != m_aPrivGuild[type].end())
it->second = p;
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 end = now+duration_sec;
// 이전 설정값 무효화
// priority_queue에 들어있는 pointer == m_aaPrivEmpire[type][empire]
// 이전 설정값 무효화
// priority_queue에 들어있는 pointer == m_aaPrivEmpire[type][empire]
{
if (m_aaPrivEmpire[type][empire])
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
{

View File

@ -25,23 +25,23 @@ string trim(const string& str){return trim_left(trim_right(str));}
static string* StringSplit(string strOrigin, string strTok)
{
int cutAt; //자르는위치
int index = 0; //문자열인덱스
string* strResult = new string[30]; //결과return 할변수
int cutAt; //자르는위치
int index = 0; //문자열인덱스
string* strResult = new string[30]; //결과return 할변수
//strTok을찾을때까지반복
//strTok을찾을때까지반복
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++)
@ -49,7 +49,7 @@ static string* StringSplit(string strOrigin, string strTok)
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_AUTOUSE", "ITEM_MATERIAL",
"ITEM_SPECIAL", "ITEM_TOOL",
"ITEM_LOTTERY", "ITEM_ELK", //10개
"ITEM_LOTTERY", "ITEM_ELK", //10개
"ITEM_METIN", "ITEM_CONTAINER",
"ITEM_FISH", "ITEM_ROD",
"ITEM_RESOURCE", "ITEM_CAMPFIRE",
"ITEM_UNIQUE", "ITEM_SKILLBOOK",
"ITEM_QUEST", "ITEM_POLYMORPH", //20개
"ITEM_QUEST", "ITEM_POLYMORPH", //20개
"ITEM_TREASURE_BOX", "ITEM_TREASURE_KEY",
"ITEM_SKILLFORGET", "ITEM_GIFTBOX",
"ITEM_PICK", "ITEM_HAIR",
"ITEM_TOTEM", "ITEM_BLEND",
"ITEM_COSTUME", "ITEM_DS", //30개
"ITEM_COSTUME", "ITEM_DS", //30개
"ITEM_SPECIAL_DS", "ITEM_EXTRACT",
"ITEM_SECONDARY_COIN", //33개
"ITEM_SECONDARY_COIN", //33개
"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
arSub31, //31
0, //32
0, //33 반지
0, //34 벨트
0, //33 반지
0, //34 벨트
};
static int arNumberOfSubtype[_countof(arSubType)] = {
0,
@ -196,21 +196,21 @@ int get_Item_SubType_Value(int type_value, string inputString)
sizeof(arSub29)/sizeof(arSub29[0]),
sizeof(arSub31)/sizeof(arSub31[0]),
0, // 32
0, // 33 반지
0, // 34 벨트
0, // 33 반지
0, // 34 벨트
};
assert(_countof(arSubType) > type_value && "Subtype rule: Out of range!!");
// assert 안 먹히는 듯..
// assert 안 먹히는 듯..
if (_countof(arSubType) <= type_value)
{
SPDLOG_ERROR("SubType : Out of range!! (type_value: {}, count of registered subtype: {}", type_value, _countof(arSubType));
return -1;
}
//아이템 타입의 서브타입 어레이가 존재하는지 알아보고, 없으면 0 리턴
//아이템 타입의 서브타입 어레이가 존재하는지 알아보고, 없으면 0 리턴
if (arSubType[type_value]==0) {
return 0;
}
@ -246,13 +246,13 @@ int get_Item_AntiFlag_Value(string inputString)
int retValue = 0;
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arAntiFlag)/sizeof(arAntiFlag[0]);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];
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
retValue = retValue + pow((float)2,(float)i);
}
@ -275,13 +275,13 @@ int get_Item_Flag_Value(string inputString)
int retValue = 0;
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arFlag)/sizeof(arFlag[0]);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];
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
retValue = retValue + pow((float)2,(float)i);
}
@ -303,13 +303,13 @@ int get_Item_WearFlag_Value(string inputString)
int retValue = 0;
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arWearrFlag)/sizeof(arWearrFlag[0]);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];
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
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"};
int retValue = 0;
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
string* arInputString = StringSplit(inputString, "|"); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arImmune)/sizeof(arImmune[0]);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];
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
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)
@ -508,13 +508,13 @@ int get_Mob_AIFlag_Value(string inputString)
int retValue = 0;
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arAIFlag)/sizeof(arAIFlag[0]);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];
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
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"};
int retValue = 0;
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arRaceFlag)/sizeof(arRaceFlag[0]);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];
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
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"};
int retValue = 0;
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
string* arInputString = StringSplit(inputString, ","); //프로토 정보 내용을 단어별로 쪼갠 배열.
for(int i =0;i<sizeof(arImmuneFlag)/sizeof(arImmuneFlag[0]);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];
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
if (tempString2.compare(tempString)==0) { //일치하는지 확인.
retValue = retValue + pow((float)2,(float)i);
}
@ -581,14 +581,14 @@ int get_Mob_ImmuneFlag_Value(string inputString)
#ifndef __DUMP_PROTO__
//몹 테이블을 셋팅해준다.
//몹 테이블을 셋팅해준다.
bool Set_Proto_Mob_Table(TMobTable *mobTable, cCsvTable &csvTable,std::map<int,const char*> &nameMap)
{
int col = 0;
str_to_number(mobTable->dwVnum, csvTable.AsStringByIndex(col++));
strlcpy(mobTable->szName, csvTable.AsStringByIndex(col++), sizeof(mobTable->szName));
//3. 지역별 이름 넣어주기.
//3. 지역별 이름 넣어주기.
map<int,const char*>::iterator it;
it = nameMap.find(mobTable->dwVnum);
if (it != nameMap.end()) {
@ -749,11 +749,11 @@ bool Set_Proto_Item_Table(TItemTable *itemTable, cCsvTable &csvTable,std::map<in
col = col + 1;
}
// vnum 및 vnum range 읽기.
// vnum 및 vnum range 읽기.
{
std::string s(csvTable.AsStringByIndex(0));
int pos = s.find("~");
// vnum 필드에 '~'가 없다면 패스
// vnum 필드에 '~'가 없다면 패스
if (std::string::npos == pos)
{
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));
//지역별 이름 넣어주기.
//지역별 이름 넣어주기.
map<int,const char*>::iterator it;
it = nameMap.find(itemTable->dwVnum);
if (it != nameMap.end()) {

View File

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