Hi guys ,
who can ask me to read db txt not sql?Source db
Main.cpp
#include "stdafx.h"
#include "Config.h"
#include "Peer.h"
#include "DBManager.h"
#include "ClientManager.h"
#include "GuildManager.h"
#include "ItemAwardManager.h"
#include "HB.h"
#include "PrivManager.h"
#include "MoneyLog.h"
#include "Marriage.h"
#include "Monarch.h"
#include "BlockCountry.h"
#include "ItemIDRangeManager.h"
#ifdef __AUCTION__
#include "AuctionManager.h"
#endif
#include <signal.h>
void SetPlayerDBName(const char* c_pszPlayerDBName);
void SetTablePostfix(const char* c_pszTablePostfix);
int Start();
std::string g_stTablePostfix;
std::string g_stLocaleNameColumn = "name";
std::string g_stLocale = "euckr";
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 보다 길어야 한다.
int g_iLogoutSeconds = 60*10;
int g_log = 1;
// MYSHOP_PRICE_LIST
int g_iItemPriceListTableCacheFlushSeconds = 540;
// END_OF_MYSHOP_PRICE_LIST
#ifdef __FreeBSD__
extern const char * _malloc_options;
#endif
extern void WriteVersion();
void emergency_sig(int sig)
{
if (sig == SIGSEGV)
sys_log(0, "SIGNAL: SIGSEGV");
else if (sig == SIGUSR1)
sys_log(0, "SIGNAL: SIGUSR1");
if (sig == SIGSEGV)
abort();
}
int main()
{
WriteVersion();
#ifdef __FreeBSD__
_malloc_options = "A";
#endif
CConfig Config;
CNetPoller poller;
CDBManager DBManager;
CClientManager ClientManager;
PlayerHB player_hb;
CGuildManager GuildManager;
CPrivManager PrivManager;
CMoneyLog MoneyLog;
ItemAwardManager ItemAwardManager;
marriage::CManager MarriageManager;
CMonarch Monarch;
CBlockCountry BlockCountry;
CItemIDRangeManager ItemIDRangeManager;
#ifdef __AUCTION__
AuctionManager auctionManager;
#endif
if (!Start())
return 1;
GuildManager.Initialize();
MarriageManager.Initialize();
BlockCountry.Load();
ItemIDRangeManager.Build();
#ifdef __AUCTION__
AuctionManager::instance().Initialize();
#endif
sys_log(0, "Metin2DBCacheServer Start\n");
CClientManager::instance().MainLoop();
signal_timer_disable();
DBManager.Quit();
int iCount;
while (1)
{
iCount = 0;
iCount += CDBManager::instance().CountReturnQuery(SQL_PLAYER);
iCount += CDBManager::instance().CountAsyncQuery(SQL_PLAYER);
if (iCount == 0)
break;
usleep(1000);
sys_log(0, "WAITING_QUERY_COUNT %d", iCount);
}
return 1;
}
void emptybeat(LPHEART heart, int pulse)
{
if (!(pulse % heart->passes_per_sec)) // 1초에 한번
{
}
}
//
// @version 05/06/13 Bang2ni - 아이템 가격정보 캐시 flush timeout 설정 추가.
//
int Start()
{
if (!CConfig::instance().LoadFile("conf.txt"))
{
fprintf(stderr, "Loading conf.txt failed.\n");
return false;
}
if (!CConfig::instance().GetValue("TEST_SERVER", &g_test_server))
{
fprintf(stderr, "Real Server\n");
}
else
fprintf(stderr, "Test Server\n");
if (!CConfig::instance().GetValue("LOG", &g_log))
{
fprintf(stderr, "Log Off");
g_log= 0;
}
else
{
g_log = 1;
fprintf(stderr, "Log On");
}
int tmpValue;
int heart_beat = 50;
if (!CConfig::instance().GetValue("CLIENT_HEART_FPS", &heart_beat))
{
fprintf(stderr, "Cannot find CLIENT_HEART_FPS configuration.\n");
return false;
}
log_set_expiration_days(3);
if (CConfig::instance().GetValue("LOG_KEEP_DAYS", &tmpValue))
{
tmpValue = MINMAX(3, tmpValue, 30);
log_set_expiration_days(tmpValue);
fprintf(stderr, "Setting log keeping days to %d\n", tmpValue);
}
thecore_init(heart_beat, emptybeat);
signal_timer_enable(60);
char szBuf[256+1];
if (CConfig::instance().GetValue("LOCALE", szBuf, 256))
{
g_stLocale = szBuf;
sys_log(0, "LOCALE set to %s", g_stLocale.c_str());
// CHINA_DISABLE_HOTBACKUP
if ("gb2312" == g_stLocale)
{
sys_log(0, "CIBN_LOCALE: DISABLE_HOTBACKUP");
g_bHotBackup = false;
}
// END_OF_CHINA_DISABLE_HOTBACKUP
}
int iDisableHotBackup;
if (CConfig::instance().GetValue("DISABLE_HOTBACKUP", &iDisableHotBackup))
{
if (iDisableHotBackup)
{
sys_log(0, "CONFIG: DISABLE_HOTBACKUP");
g_bHotBackup = false;
}
}
if (!CConfig::instance().GetValue("TABLE_POSTFIX", szBuf, 256))
{
//sys_err("TABLE_POSTFIX not configured use default");
szBuf[0] = '\0';
}
SetTablePostfix(szBuf);
if (CConfig::instance().GetValue("PLAYER_CACHE_FLUSH_SECONDS", szBuf, 256))
{
str_to_number(g_iPlayerCacheFlushSeconds, szBuf);
sys_log(0, "PLAYER_CACHE_FLUSH_SECONDS: %d", g_iPlayerCacheFlushSeconds);
}
if (CConfig::instance().GetValue("ITEM_CACHE_FLUSH_SECONDS", szBuf, 256))
{
str_to_number(g_iItemCacheFlushSeconds, szBuf);
sys_log(0, "ITEM_CACHE_FLUSH_SECONDS: %d", g_iItemCacheFlushSeconds);
}
// MYSHOP_PRICE_LIST
if (CConfig::instance().GetValue("ITEM_PRICELIST_CACHE_FLUSH_SECONDS", szBuf, 256))
{
str_to_number(g_iItemPriceListTableCacheFlushSeconds, szBuf);
sys_log(0, "ITEM_PRICELIST_CACHE_FLUSH_SECONDS: %d", g_iItemPriceListTableCacheFlushSeconds);
}
// END_OF_MYSHOP_PRICE_LIST
//
if (CConfig::instance().GetValue("CACHE_FLUSH_LIMIT_PER_SECOND", szBuf, 256))
{
DWORD dwVal = 0; str_to_number(dwVal, szBuf);
CClientManager::instance().SetCacheFlushCountLimit(dwVal);
}
int iIDStart;
if (!CConfig::instance().GetValue("PLAYER_ID_START", &iIDStart))
{
sys_err("PLAYER_ID_START not configured");
return false;
}
CClientManager::instance().SetPlayerIDStart(iIDStart);
if (CConfig::instance().GetValue("NAME_COLUMN", szBuf, 256))
{
fprintf(stderr, "%s %s", g_stLocaleNameColumn.c_str(), szBuf);
g_stLocaleNameColumn = szBuf;
}
char szAddr[64], szDB[64], szUser[64], szPassword[64];
int iPort;
char line[256+1];
if (CConfig::instance().GetValue("SQL_PLAYER", line, 256))
{
sscanf(line, " %s %s %s %s %d ", szAddr, szDB, szUser, szPassword, &iPort);
sys_log(0, "connecting to MySQL server (player)");
int iRetry = 5;
do
{
if (CDBManager::instance().Connect(SQL_PLAYER, szAddr, iPort, szDB, szUser, szPassword))
{
sys_log(0, " OK");
break;
}
sys_log(0, " failed, retrying in 5 seconds");
fprintf(stderr, " failed, retrying in 5 seconds");
sleep(5);
} while (iRetry--);
fprintf(stderr, "Success PLAYER\n");
SetPlayerDBName(szDB);
}
else
{
sys_err("SQL_PLAYER not configured");
return false;
}
if (CConfig::instance().GetValue("SQL_ACCOUNT", line, 256))
{
sscanf(line, " %s %s %s %s %d ", szAddr, szDB, szUser, szPassword, &iPort);
sys_log(0, "connecting to MySQL server (account)");
int iRetry = 5;
do
{
if (CDBManager::instance().Connect(SQL_ACCOUNT, szAddr, iPort, szDB, szUser, szPassword))
{
sys_log(0, " OK");
break;
}
sys_log(0, " failed, retrying in 5 seconds");
fprintf(stderr, " failed, retrying in 5 seconds");
sleep(5);
} while (iRetry--);
fprintf(stderr, "Success ACCOUNT\n");
}
else
{
sys_err("SQL_ACCOUNT not configured");
return false;
}
if (CConfig::instance().GetValue("SQL_COMMON", line, 256))
{
sscanf(line, " %s %s %s %s %d ", szAddr, szDB, szUser, szPassword, &iPort);
sys_log(0, "connecting to MySQL server (common)");
int iRetry = 5;
do
{
if (CDBManager::instance().Connect(SQL_COMMON, szAddr, iPort, szDB, szUser, szPassword))
{
sys_log(0, " OK");
break;
}
sys_log(0, " failed, retrying in 5 seconds");
fprintf(stderr, " failed, retrying in 5 seconds");
sleep(5);
} while (iRetry--);
fprintf(stderr, "Success COMMON\n");
}
else
{
sys_err("SQL_COMMON not configured");
return false;
}
if (CConfig::instance().GetValue("SQL_HOTBACKUP", line, 256))
{
sscanf(line, " %s %s %s %s %d ", szAddr, szDB, szUser, szPassword, &iPort);
sys_log(0, "connecting to MySQL server (hotbackup)");
int iRetry = 5;
do
{
if (CDBManager::instance().Connect(SQL_HOTBACKUP, szAddr, iPort, szDB, szUser, szPassword))
{
sys_log(0, " OK");
break;
}
sys_log(0, " failed, retrying in 5 seconds");
fprintf(stderr, " failed, retrying in 5 seconds");
sleep(5);
}
while (iRetry--);
fprintf(stderr, "Success HOTBACKUP\n");
}
else
{
sys_err("SQL_HOTBACKUP not configured");
return false;
}
if (!CNetPoller::instance().Create())
{
sys_err("Cannot create network poller");
return false;
}
sys_log(0, "ClientManager initialization.. ");
if (!CClientManager::instance().Initialize())
{
sys_log(0, " failed");
return false;
}
sys_log(0, " OK");
if (!PlayerHB::instance().Initialize())
{
sys_err("cannot initialize player hotbackup");
return false;
}
#ifndef __WIN32__
signal(SIGUSR1, emergency_sig);
#endif
signal(SIGSEGV, emergency_sig);
return true;
}
void SetTablePostfix(const char* c_pszTablePostfix)
{
if (!c_pszTablePostfix !*c_pszTablePostfix)
g_stTablePostfix = "";
else
g_stTablePostfix = c_pszTablePostfix;
}
const char * GetTablePostfix()
{
return g_stTablePostfix.c_str();
}
void SetPlayerDBName(const char* c_pszPlayerDBName)
{
if (! c_pszPlayerDBName ! *c_pszPlayerDBName)
g_stPlayerDBName = "";
else
{
g_stPlayerDBName = c_pszPlayerDBName;
g_stPlayerDBName += ".";
}
}
const char * GetPlayerDBName()
{
return g_stPlayerDBName.c_str();
}
ClientManager.h
// vim:ts=8 sw=4
#ifndef __INC_CLIENTMANAGER_H__
#define __INC_CLIENTMANAGER_H__
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>
#include "../../common/stl.h"
#include "../../common/building.h"
#include "../../common/auction_table.h"
#include "Peer.h"
#include "DBManager.h"
#include "LoginData.h"
class CPlayerTableCache;
class CItemCache;
class CItemPriceListTableCache;
class CPacketInfo
{
public:
void Add(int header);
void Reset();
std::map<int, int> m_map_info;
};
size_t CreatePlayerSaveQuery(char * pszQuery, size_t querySize, TPlayerTable * pkTab);
class CClientManager : public CNetBase, public singleton<CClientManager>
{
public:
typedef std::list<CPeer *> TPeerList;
typedef boost::unordered_map<DWORD, CPlayerTableCache *> TPlayerTableCacheMap;
typedef boost::unordered_map<DWORD, CItemCache *> TItemCacheMap;
typedef boost::unordered_set<CItemCache *, boost::hash<CItemCache*> > TItemCacheSet;
typedef boost::unordered_map<DWORD, TItemCacheSet *> TItemCacheSetPtrMap;
typedef boost::unordered_map<DWORD, CItemPriceListTableCache*> TItemPriceListCacheMap;
typedef boost::unordered_map<short, BYTE> TChannelStatusMap;
// MYSHOP_PRICE_LIST
/// 아이템 가격정보 리스트 요청 정보
/**
* first: Peer handle
* second: 요청한 플레이어의 ID
*/
typedef std::pair< DWORD, DWORD > TItemPricelistReqInfo;
// END_OF_MYSHOP_PRICE_LIST
class ClientHandleInfo
{
public:
DWORD dwHandle;
DWORD account_id;
DWORD player_id;
BYTE account_index;
char login[LOGIN_MAX_LEN + 1];
char safebox_password[SAFEBOX_PASSWORD_MAX_LEN + 1];
char ip[MAX_HOST_LENGTH + 1];
TAccountTable * pAccountTable;
TSafeboxTable * pSafebox;
ClientHandleInfo(DWORD argHandle, DWORD dwPID = 0)
{
dwHandle = argHandle;
pSafebox = NULL;
pAccountTable = NULL;
player_id = dwPID;
};
//독일선물기능용 생성자
ClientHandleInfo(DWORD argHandle, DWORD dwPID, DWORD accountId)
{
dwHandle = argHandle;
pSafebox = NULL;
pAccountTable = NULL;
player_id = dwPID;
account_id = accountId;
};
~ClientHandleInfo()
{
if (pSafebox)
{
delete pSafebox;
pSafebox = NULL;
}
}
};
public:
CClientManager();
~CClientManager();
bool Initialize();
time_t GetCurrentTime();
void MainLoop();
void Quit();
void SetTablePostfix(const char* c_pszTablePostfix);
void SetPlayerIDStart(int iIDStart);
int GetPlayerIDStart() { return m_iPlayerIDStart; }
int GetPlayerDeleteLevelLimit() { return m_iPlayerDeleteLevelLimit; }
void SetChinaEventServer(bool flag) { m_bChinaEventServer = flag; }
bool IsChinaEventServer() { return m_bChinaEventServer; }
DWORD GetUserCount(); // 접속된 사용자 수를 리턴 한다.
void SendAllGuildSkillRechargePacket();
void SendTime();
CPlayerTableCache * GetPlayerCache(DWORD id);
void PutPlayerCache(TPlayerTable * pNew);
void CreateItemCacheSet(DWORD dwID);
TItemCacheSet * GetItemCacheSet(DWORD dwID);
void FlushItemCacheSet(DWORD dwID);
CItemCache * GetItemCache(DWORD id);
void PutItemCache(TPlayerItem * pNew, bool bSkipQuery = false);
bool DeleteItemCache(DWORD id);
void UpdatePlayerCache();
void UpdateItemCache();
// MYSHOP_PRICE_LIST
/// 가격정보 리스트 캐시를 가져온다.
/**
* @param [in] dwID 가격정보 리스트의 소유자.(플레이어 ID)
* @return 가격정보 리스트 캐시의 포인터
*/
CItemPriceListTableCache* GetItemPriceListCache(DWORD dwID);
/// 가격정보 리스트 캐시를 넣는다.
/**
* @param [in] pItemPriceList 캐시에 넣을 아이템 가격정보 리스트
*
* 캐시가 이미 있으면 Update 가 아닌 replace 한다.
*/
void PutItemPriceListCache(const TItemPriceListTable* pItemPriceList);
/// Flush 시간이 만료된 아이템 가격정보 리스트 캐시를 Flush 해주고 캐시에서 삭제한다.
void UpdateItemPriceListCache(void);
// END_OF_MYSHOP_PRICE_LIST
void SendGuildSkillUsable(DWORD guild_id, DWORD dwSkillVnum, bool bUsable);
void SetCacheFlushCountLimit(int iLimit);
template <class Func>
Func for_each_peer(Func f);
CPeer * GetAnyPeer();
void ForwardPacket(BYTE header, const void* data, int size, BYTE bChannel = 0, CPeer * except = NULL);
void SendNotice(const char * c_pszFormat, ...);
char* GetCommand(char* str); //독일선물기능에서 명령어 얻는 함수
void ItemAward(CPeer * peer, char* login); //독일 선물 기능
protected:
void Destroy();
private:
bool InitializeTables();
bool InitializeShopTable();
bool InitializeMobTable();
bool InitializeItemTable();
bool InitializeQuestItemTable();
bool InitializeSkillTable();
bool InitializeRefineTable();
bool InitializeBanwordTable();
bool InitializeItemAttrTable();
bool InitializeItemRareTable();
bool InitializeLandTable();
bool InitializeObjectProto();
bool InitializeObjectTable();
bool InitializeMonarch();
// mob_proto.txt, item_proto.txt에서 읽은 mob_proto, item_proto를 real db에 반영.
// item_proto, mob_proto를 db에 반영하지 않아도, 게임 돌아가는데는 문제가 없지만,
// 운영툴 등에서 db의 item_proto, mob_proto를 읽어 쓰기 때문에 문제가 발생한다.
bool MirrorMobTableIntoDB();
bool MirrorItemTableIntoDB();
void AddPeer(socket_t fd);
void RemovePeer(CPeer * pPeer);
CPeer * GetPeer(IDENT ident);
int AnalyzeQueryResult(SQLMsg * msg);
int AnalyzeErrorMsg(CPeer * peer, SQLMsg * msg);
int Process();
void ProcessPackets(CPeer * peer);
CLoginData * GetLoginData(DWORD dwKey);
CLoginData * GetLoginDataByLogin(const char * c_pszLogin);
CLoginData * GetLoginDataByAID(DWORD dwAID);
void InsertLoginData(CLoginData * pkLD);
void DeleteLoginData(CLoginData * pkLD);
bool InsertLogonAccount(const char * c_pszLogin, DWORD dwHandle, const char * c_pszIP);
bool DeleteLogonAccount(const char * c_pszLogin, DWORD dwHandle);
bool FindLogonAccount(const char * c_pszLogin);
void GuildCreate(CPeer * peer, DWORD dwGuildID);
void GuildSkillUpdate(CPeer * peer, TPacketGuildSkillUpdate* p);
void GuildExpUpdate(CPeer * peer, TPacketGuildExpUpdate* p);
void GuildAddMember(CPeer * peer, TPacketGDGuildAddMember* p);
void GuildChangeGrade(CPeer * peer, TPacketGuild* p);
void GuildRemoveMember(CPeer * peer, TPacketGuild* p);
void GuildChangeMemberData(CPeer * peer, TPacketGuildChangeMemberData* p);
void GuildDisband(CPeer * peer, TPacketGuild * p);
void GuildWar(CPeer * peer, TPacketGuildWar * p);
void GuildWarScore(CPeer * peer, TPacketGuildWarScore * p);
void GuildChangeLadderPoint(TPacketGuildLadderPoint* p);
void GuildUseSkill(TPacketGuildUseSkill* p);
void GuildDepositMoney(TPacketGDGuildMoney* p);
void GuildWithdrawMoney(CPeer* peer, TPacketGDGuildMoney* p);
void GuildWithdrawMoneyGiveReply(TPacketGDGuildMoneyWithdrawGiveReply* p);
void GuildWarBet(TPacketGDGuildWarBet * p);
void GuildChangeMaster(TPacketChangeGuildMaster* p);
void SetGuildWarEndTime(DWORD guild_id1, DWORD guild_id2, time_t tEndTime);
void QUERY_BOOT(CPeer * peer, TPacketGDBoot * p);
void QUERY_LOGIN(CPeer * peer, DWORD dwHandle, SLoginPacket* data);
void QUERY_LOGOUT(CPeer * peer, DWORD dwHandle, const char *);
void RESULT_LOGIN(CPeer * peer, SQLMsg *msg);
void QUERY_PLAYER_LOAD(CPeer * peer, DWORD dwHandle, TPlayerLoadPacket*);
void RESULT_COMPOSITE_PLAYER(CPeer * peer, SQLMsg * pMsg, DWORD dwQID);
void RESULT_PLAYER_LOAD(CPeer * peer, MYSQL_RES * pRes, ClientHandleInfo * pkInfo);
void RESULT_ITEM_LOAD(CPeer * peer, MYSQL_RES * pRes, DWORD dwHandle, DWORD dwPID);
void RESULT_QUEST_LOAD(CPeer * pkPeer, MYSQL_RES * pRes, DWORD dwHandle, DWORD dwPID);
void RESULT_AFFECT_LOAD(CPeer * pkPeer, MYSQL_RES * pRes, DWORD dwHandle);
// PLAYER_INDEX_CREATE_BUG_FIX
void RESULT_PLAYER_INDEX_CREATE(CPeer *pkPeer, SQLMsg *msg);
// END_PLAYER_INDEX_CREATE_BUG_FIX
// MYSHOP_PRICE_LIST
/// 가격정보 로드 쿼리에 대한 Result 처리
/**
* @param peer 가격정보를 요청한 Game server 의 peer 객체 포인터
* @param pMsg 쿼리의 Result 로 받은 객체의 포인터
*
* 로드된 가격정보 리스트를 캐시에 저장하고 peer 에게 리스트를 보내준다.
*/
void RESULT_PRICELIST_LOAD(CPeer* peer, SQLMsg* pMsg);
/// 가격정보 업데이트를 위한 로드 쿼리에 대한 Result 처리
/**
* @param pMsg 쿼리의 Result 로 받은 객체의 포인터
*
* 로드된 정보로 가격정보 리스트 캐시를 만들고 업데이트 받은 가격정보로 업데이트 한다.
*/
void RESULT_PRICELIST_LOAD_FOR_UPDATE(SQLMsg* pMsg);
// END_OF_MYSHOP_PRICE_LIST
void QUERY_PLAYER_SAVE(CPeer * peer, DWORD dwHandle, TPlayerTable*);
void __QUERY_PLAYER_CREATE(CPeer * peer, DWORD dwHandle, TPlayerCreatePacket *);
void __QUERY_PLAYER_DELETE(CPeer * peer, DWORD dwHandle, TPlayerDeletePacket *);
void __RESULT_PLAYER_DELETE(CPeer * peer, SQLMsg* msg);
void QUERY_PLAYER_COUNT(CPeer * pkPeer, TPlayerCountPacket *);
void QUERY_ITEM_SAVE(CPeer * pkPeer, const char * c_pData);
void QUERY_ITEM_DESTROY(CPeer * pkPeer, const char * c_pData);
void QUERY_ITEM_FLUSH(CPeer * pkPeer, const char * c_pData);
void QUERY_QUEST_SAVE(CPeer * pkPeer, TQuestTable *, DWORD dwLen);
void QUERY_ADD_AFFECT(CPeer * pkPeer, TPacketGDAddAffect * p);
void QUERY_REMOVE_AFFECT(CPeer * pkPeer, TPacketGDRemoveAffect * p);
void QUERY_SAFEBOX_LOAD(CPeer * pkPeer, DWORD dwHandle, TSafeboxLoadPacket *, bool bMall);
void QUERY_SAFEBOX_SAVE(CPeer * pkPeer, TSafeboxTable * pTable);
void QUERY_SAFEBOX_CHANGE_SIZE(CPeer * pkPeer, DWORD dwHandle, TSafeboxChangeSizePacket * p);
void QUERY_SAFEBOX_CHANGE_PASSWORD(CPeer * pkPeer, DWORD dwHandle, TSafeboxChangePasswordPacket * p);
void RESULT_SAFEBOX_LOAD(CPeer * pkPeer, SQLMsg * msg);
void RESULT_SAFEBOX_CHANGE_SIZE(CPeer * pkPeer, SQLMsg * msg);
void RESULT_SAFEBOX_CHANGE_PASSWORD(CPeer * pkPeer, SQLMsg * msg);
void RESULT_SAFEBOX_CHANGE_PASSWORD_SECOND(CPeer * pkPeer, SQLMsg * msg);
void QUERY_EMPIRE_SELECT(CPeer * pkPeer, DWORD dwHandle, TEmpireSelectPacket * p);
void QUERY_SETUP(CPeer * pkPeer, DWORD dwHandle, const char * c_pData);
void SendPartyOnSetup(CPeer * peer);
void QUERY_HIGHSCORE_REGISTER(CPeer * peer, TPacketGDHighscore* data);
void RESULT_HIGHSCORE_REGISTER(CPeer * pkPeer, SQLMsg * msg);
void QUERY_FLUSH_CACHE(CPeer * pkPeer, const char * c_pData);
void QUERY_PARTY_CREATE(CPeer * peer, TPacketPartyCreate* p);
void QUERY_PARTY_DELETE(CPeer * peer, TPacketPartyDelete* p);
void QUERY_PARTY_ADD(CPeer * peer, TPacketPartyAdd* p);
void QUERY_PARTY_REMOVE(CPeer * peer, TPacketPartyRemove* p);
void QUERY_PARTY_STATE_CHANGE(CPeer * peer, TPacketPartyStateChange* p);
void QUERY_PARTY_SET_MEMBER_LEVEL(CPeer * peer, TPacketPartySetMemberLevel* p);
void QUERY_RELOAD_PROTO();
void QUERY_CHANGE_NAME(CPeer * peer, DWORD dwHandle, TPacketGDChangeName * p);
void GetPlayerFromRes(TPlayerTable * player_table, MYSQL_RES* res);
void QUERY_SMS(CPeer * pkPeer, TPacketGDSMS * p);
void QUERY_LOGIN_KEY(CPeer * pkPeer, TPacketGDLoginKey * p);
void AddGuildPriv(TPacketGiveGuildPriv* p);
void AddEmpirePriv(TPacketGiveEmpirePriv* p);
void AddCharacterPriv(TPacketGiveCharacterPriv* p);
void MoneyLog(TPacketMoneyLog* p);
void QUERY_AUTH_LOGIN(CPeer * pkPeer, DWORD dwHandle, TPacketGDAuthLogin * p);
void QUERY_LOGIN_BY_KEY(CPeer * pkPeer, DWORD dwHandle, TPacketGDLoginByKey * p);
void RESULT_LOGIN_BY_KEY(CPeer * peer, SQLMsg * msg);
void ChargeCash(const TRequestChargeCash * p);
void LoadEventFlag();
void SetEventFlag(TPacketSetEventFlag* p);
void SendEventFlagsOnSetup(CPeer* peer);
void BillingExpire(TPacketBillingExpire * p);
void BillingCheck(const char * data);
void SendAllLoginToBilling();
void SendLoginToBilling(CLoginData * pkLD, bool bLogin);
// 결혼
void MarriageAdd(TPacketMarriageAdd * p);
void MarriageUpdate(TPacketMarriageUpdate * p);
void MarriageRemove(TPacketMarriageRemove * p);
void WeddingRequest(TPacketWeddingRequest * p);
void WeddingReady(TPacketWeddingReady * p);
void WeddingEnd(TPacketWeddingEnd * p);
// MYSHOP_PRICE_LIST
// 개인상점 가격정보
/// 아이템 가격정보 리스트 업데이트 패킷(HEADER_GD_MYSHOP_PRICELIST_UPDATE) 처리함수
/**
* @param [in] pPacket 패킷 데이터의 포인터
*/
void MyshopPricelistUpdate(const TPacketMyshopPricelistHeader* pPacket);
/// 아이템 가격정보 리스트 요청 패킷(HEADER_GD_MYSHOP_PRICELIST_REQ) 처리함수
/**
* @param peer 패킷을 보낸 Game server 의 peer 객체의 포인터
* @param [in] dwHandle 가격정보를 요청한 peer 의 핸들
* @param [in] dwPlayerID 가격정보 리스트를 요청한 플레이어의 ID
*/
void MyshopPricelistRequest(CPeer* peer, DWORD dwHandle, DWORD dwPlayerID);
// END_OF_MYSHOP_PRICE_LIST
// Building
void CreateObject(TPacketGDCreateObject * p);
void DeleteObject(DWORD dwID);
void UpdateLand(DWORD * pdw);
// VCard
void VCard(TPacketGDVCard * p);
void VCardProcess();
// BLOCK_CHAT
void BlockChat(TPacketBlockChat * p);
// END_OF_BLOCK_CHAT
private:
int m_looping;
socket_t m_fdAccept; // 접속 받는 소켓
TPeerList m_peerList;
CPeer * m_pkAuthPeer;
// LoginKey, LoginData pair
typedef boost::unordered_map<DWORD, CLoginData *> TLoginDataByLoginKey;
TLoginDataByLoginKey m_map_pkLoginData;
// Login LoginData pair
typedef boost::unordered_map<std::string, CLoginData *> TLoginDataByLogin;
TLoginDataByLogin m_map_pkLoginDataByLogin;
// AccountID LoginData pair
typedef boost::unordered_map<DWORD, CLoginData *> TLoginDataByAID;
TLoginDataByAID m_map_pkLoginDataByAID;
// Login LoginData pair (실제 로그인 되어있는 계정)
typedef boost::unordered_map<std::string, CLoginData *> TLogonAccountMap;
TLogonAccountMap m_map_kLogonAccount;
int m_iPlayerIDStart;
int m_iPlayerDeleteLevelLimit;
int m_iPlayerDeleteLevelLimitLower;
bool m_bChinaEventServer;
std::vector<TMobTable> m_vec_mobTable;
std::vector<TItemTable> m_vec_itemTable;
std::map<DWORD, TItemTable *> m_map_itemTableByVnum;
int m_iShopTableSize;
TShopTable * m_pShopTable;
int m_iRefineTableSize;
TRefineTable* m_pRefineTable;
std::vector<TSkillTable> m_vec_skillTable;
std::vector<TBanwordTable> m_vec_banwordTable;
std::vector<TItemAttrTable> m_vec_itemAttrTable;
std::vector<TItemAttrTable> m_vec_itemRareTable;
std::vector<building::TLand> m_vec_kLandTable;
std::vector<building::TObjectProto> m_vec_kObjectProto;
std::map<DWORD, building::TObject *> m_map_pkObjectTable;
std::queue<TPacketGDVCard> m_queue_vcard;
bool m_bShutdowned;
TPlayerTableCacheMap m_map_playerCache; // 플레이어 id가 key
TItemCacheMap m_map_itemCache; // 아이템 id가 key
TItemCacheSetPtrMap m_map_pkItemCacheSetPtr; // 플레이어 id가 key, 이 플레이어가 어떤 아이템 캐쉬를 가지고 있나?
// MYSHOP_PRICE_LIST
/// 플레이어별 아이템 가격정보 리스트 map. key: 플레이어 ID, value: 가격정보 리스트 캐시
TItemPriceListCacheMap m_mapItemPriceListCache; ///< 플레이어별 아이템 가격정보 리스트
// END_OF_MYSHOP_PRICE_LIST
TChannelStatusMap m_mChannelStatus;
struct TPartyInfo
{
BYTE bRole;
BYTE bLevel;
TPartyInfo() :bRole(0), bLevel(0)
{
}
};
typedef std::map<DWORD, TPartyInfo> TPartyMember;
typedef std::map<DWORD, TPartyMember> TPartyMap;
typedef std::map<BYTE, TPartyMap> TPartyChannelMap;
TPartyChannelMap m_map_pkChannelParty;
typedef std::map<std::string, long> TEventFlagMap;
TEventFlagMap m_map_lEventFlag;
BYTE m_bLastHeader;
int m_iCacheFlushCount;
int m_iCacheFlushCountLimit;
private :
TItemIDRangeTable m_itemRange;
public :
bool InitializeNowItemID();
DWORD GetItemID();
DWORD GainItemID();
TItemIDRangeTable GetItemRange() { return m_itemRange; }
//BOOT_LOCALIZATION
public:
/* 로컬 정보 초기화
**/
bool InitializeLocalization();
private:
std::vector<tLocale> m_vec_Locale;
//END_BOOT_LOCALIZATION
//ADMIN_MANAGER
bool __GetAdminInfo(const char *szIP, std::vector<tAdminInfo> & rAdminVec);
bool __GetHostInfo(std::vector<std::string> & rIPVec);
//END_ADMIN_MANAGER
//RELOAD_ADMIN
void ReloadAdmin(CPeer * peer, TPacketReloadAdmin * p);
//END_RELOAD_ADMIN
void BreakMarriage(CPeer * peer, const char * data);
struct TLogoutPlayer
{
DWORD pid;
time_t time;
bool operator < (const TLogoutPlayer & r)
{
return (pid < r.pid);
}
};
typedef boost::unordered_map<DWORD, TLogoutPlayer*> TLogoutPlayerMap;
TLogoutPlayerMap m_map_logout;
void InsertLogoutPlayer(DWORD pid);
void DeleteLogoutPlayer(DWORD pid);
void UpdateLogoutPlayer();
void UpdateItemCacheSet(DWORD pid);
void FlushPlayerCacheSet(DWORD pid);
//MONARCH
void Election(CPeer * peer, DWORD dwHandle, const char * p);
void Candidacy(CPeer * peer, DWORD dwHandle, const char * p);
void AddMonarchMoney(CPeer * peer, DWORD dwHandle, const char * p);
void TakeMonarchMoney(CPeer * peer, DWORD dwHandle, const char * p);
void ComeToVote(CPeer * peer, DWORD dwHandle, const char * p);
void RMCandidacy(CPeer * peer, DWORD dwHandle, const char * p);
void SetMonarch(CPeer * peer, DWORD dwHandle, const char * p);
void RMMonarch(CPeer * peer, DWORD dwHandle, const char * p);
void DecMonarchMoney(CPeer * peer, DWORD dwHandle, const char * p);
//END_MONARCH
void ChangeMonarchLord(CPeer* peer, DWORD dwHandle, TPacketChangeMonarchLord* info);
void BlockException(TPacketBlockException *data);
void SendSpareItemIDRange(CPeer* peer);
void UpdateHorseName(TPacketUpdateHorseName* data, CPeer* peer);
void AckHorseName(DWORD dwPID, CPeer* peer);
void DeleteLoginKey(TPacketDC *data);
void ResetLastPlayerID(const TPacketNeedLoginLogInfo* data);
//delete gift notify icon
void DeleteAwardId(TPacketDeleteAwardID* data);
void UpdateChannelStatus(TChannelStatus* pData);
void RequestChannelStatus(CPeer* peer, DWORD dwHandle);
#ifdef __AUCTION__
void EnrollInAuction (CPeer * peer, DWORD owner_id, AuctionEnrollProductInfo* data);
void EnrollInSale (CPeer * peer, DWORD owner_id, AuctionEnrollSaleInfo* data);
void EnrollInWish (CPeer * peer, DWORD wisher_id, AuctionEnrollWishInfo* data);
void AuctionBid (CPeer * peer, DWORD bidder_id, AuctionBidInfo* data);
void AuctionImpur (CPeer * peer, DWORD purchaser_id, AuctionImpurInfo* data);
void AuctionGetAuctionedItem (CPeer * peer, DWORD actor_id, DWORD item_id);
void AuctionBuySoldItem (CPeer * peer, DWORD actor_id, DWORD item_id);
void AuctionCancelAuction (CPeer * peer, DWORD actor_id, DWORD item_id);
void AuctionCancelWish (CPeer * peer, DWORD actor_id, DWORD item_num);
void AuctionCancelSale (CPeer * peer, DWORD actor_id, DWORD item_id);
void AuctionDeleteAuctionItem (CPeer * peer, DWORD actor_id, DWORD item_id);
void AuctionDeleteSaleItem (CPeer * peer, DWORD actor_id, DWORD item_id);
void AuctionReBid (CPeer * peer, DWORD bidder_id, AuctionBidInfo* data);
void AuctionBidCancel (CPeer * peer, DWORD bidder_id, DWORD item_id);
#endif
};
template<class Func>
Func CClientManager::for_each_peer(Func f)
{
TPeerList::iterator it;
for (it = m_peerList.begin(); it!=m_peerList.end();++it)
{
f(*it);
}
return f;
}
#endif
ClientManagerBoot.cpp
// vim:ts=4 sw=4
#include <map>
#include "stdafx.h"
#include "ClientManager.h"
#include "Main.h"
#include "Monarch.h"
#include "CsvReader.h"
#include "ProtoReader.h"
using namespace std;
extern int g_test_server;
extern std::string g_stLocaleNameColumn;
bool CClientManager::InitializeTables()
{
if (!InitializeMobTable())
{
sys_err("InitializeMobTable FAILED");
return false;
}
/*if (!MirrorMobTableIntoDB())
{
sys_err("MirrorMobTableIntoDB FAILED");
return false;
}*/
if (!InitializeItemTable())
{
sys_err("InitializeItemTable FAILED");
return false;
}
/*if (!MirrorItemTableIntoDB())
{
sys_err("MirrorItemTableIntoDB FAILED");
return false;
}*/
if (!InitializeShopTable())
{
sys_err("InitializeShopTable FAILED");
return false;
}
if (!InitializeSkillTable())
{
sys_err("InitializeSkillTable FAILED");
return false;
}
if (!InitializeRefineTable())
{
sys_err("InitializeRefineTable FAILED");
return false;
}
if (!InitializeItemAttrTable())
{
sys_err("InitializeItemAttrTable FAILED");
return false;
}
if (!InitializeItemRareTable())
{
sys_err("InitializeItemRareTable FAILED");
return false;
}
if (!InitializeBanwordTable())
{
sys_err("InitializeBanwordTable FAILED");
return false;
}
if (!InitializeLandTable())
{
sys_err("InitializeLandTable FAILED");
return false;
}
if (!InitializeObjectProto())
{
sys_err("InitializeObjectProto FAILED");
return false;
}
if (!InitializeObjectTable())
{
sys_err("InitializeObjectTable FAILED");
return false;
}
if (!InitializeMonarch())
{
sys_err("InitializeMonarch FAILED");
return false;
}
return true;
}
bool CClientManager::InitializeRefineTable()
{
char query[2048];
snprintf(query, sizeof(query),
"SELECT id, cost, prob, vnum0, count0, vnum1, count1, vnum2, count2, vnum3, count3, vnum4, count4 FROM refine_proto%s",
GetTablePostfix());
std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query));
SQLResult * pRes = pkMsg->Get();
if (!pRes->uiNumRows)
return true;
if (m_pRefineTable)
{
sys_log(0, "RELOAD: refine_proto");
delete [] m_pRefineTable;
m_pRefineTable = NULL;
}
m_iRefineTableSize = pRes->uiNumRows;
m_pRefineTable = new TRefineTable[m_iRefineTableSize];
memset(m_pRefineTable, 0, sizeof(TRefineTable) * m_iRefineTableSize);
TRefineTable* prt = m_pRefineTable;
MYSQL_ROW data;
while ((data = mysql_fetch_row(pRes->pSQLResult)))
{
//const char* s_szQuery = "SELECT src_vnum, result_vnum, cost, prob, "
//"vnum0, count0, vnum1, count1, vnum2, count2, vnum3, count3, vnum4, count4 "
int col = 0;
//prt->src_vnum = atoi(data[col++]);
//prt->result_vnum = atoi(data[col++]);
str_to_number(prt->id, data[col++]);
str_to_number(prt->cost, data[col++]);
str_to_number(prt->prob, data[col++]);
for (int i = 0; i < REFINE_MATERIAL_MAX_NUM; i++)
{
str_to_number(prt->materials[i].vnum, data[col++]);
str_to_number(prt->materials[i].count, data[col++]);
if (prt->materials[i].vnum == 0)
{
prt->material_count = i;
break;
}
}
sys_log(0, "REFINE: id %ld cost %d prob %d mat1 %lu cnt1 %d", prt->id, prt->cost, prt->prob, prt->materials[0].vnum, prt->materials[0].count);
prt++;
}
return true;
}
class FCompareVnum
{
public:
bool operator () (const TEntityTable & a, const TEntityTable & b) const
{
return (a.dwVnum < b.dwVnum);
}
};
bool CClientManager::InitializeMobTable()
{
char query[4096];
snprintf(query, sizeof(query),
"SELECT vnum, name, %s, type, rank, battle_type, level, "
"size+0, ai_flag+0, setRaceFlag+0, setImmuneFlag+0, "
"on_click, empire, drop_item, resurrection_vnum, folder, "
"st, dx, ht, iq, damage_min, damage_max, max_hp, regen_cycle, regen_percent, exp, "
"gold_min, gold_max, def, attack_speed, move_speed, "
"aggressive_hp_pct, aggressive_sight, attack_range, polymorph_item, "
"enchant_curse, enchant_slow, enchant_poison, enchant_stun, enchant_critical, enchant_penetrate, "
"resist_sword, resist_twohand, resist_dagger, resist_bell, resist_fan, resist_bow, "
"resist_fire, resist_elect, resist_magic, resist_wind, resist_poison, "
"dam_multiply, summon, drain_sp, "
"skill_vnum0, skill_level0, skill_vnum1, skill_level1, skill_vnum2, skill_level2,"
"skill_vnum3, skill_level3, skill_vnum4, skill_level4 , sp_berserk, sp_stoneskin, "
"sp_godspeed, sp_deathblow, sp_revive "
"FROM mob_proto%s ORDER BY vnum",
g_stLocaleNameColumn.c_str(), GetTablePostfix());
std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query));
SQLResult * pRes = pkMsg->Get();
if (!pRes->uiNumRows)
{
sys_err("Could not load mob_proto. No results!");
return false;
}
sys_log(0, "MOB_PROTO loading...");
if (!m_vec_mobTable.empty())
{
sys_log(0, "RELOAD: mob_proto");
m_vec_mobTable.clear();
}
m_vec_mobTable.resize(pRes->uiNumRows);
memset(&m_vec_mobTable[0], 0, sizeof(TMobTable) * m_vec_mobTable.size());
TMobTable * mob_table = &m_vec_mobTable[0];
MYSQL_ROW data;
int col;
while ((data = mysql_fetch_row(pRes->pSQLResult)))
{
col = 0;
str_to_number(mob_table->dwVnum, data[col++]);
strlcpy(mob_table->szName, data[col++], sizeof(mob_table->szName));
strlcpy(mob_table->szLocaleName, data[col++], sizeof(mob_table->szLocaleName));
str_to_number(mob_table->bType, data[col++]);
str_to_number(mob_table->bRank, data[col++]);
str_to_number(mob_table->bBattleType, data[col++]);
str_to_number(mob_table->bLevel, data[col++]);
str_to_number(mob_table->bSize, data[col++]);
str_to_number(mob_table->dwAIFlag, data[col++]);
str_to_number(mob_table->dwRaceFlag, data[col++]);
str_to_number(mob_table->dwImmuneFlag, data[col++]);
str_to_number(mob_table->bOnClickType, data[col++]);
str_to_number(mob_table->bEmpire, data[col++]);
str_to_number(mob_table->dwDropItemVnum, data[col++]);
str_to_number(mob_table->dwResurrectionVnum, data[col++]);
strlcpy(mob_table->szFolder, data[col++], sizeof(mob_table->szFolder));
str_to_number(mob_table->bStr, data[col++]);
str_to_number(mob_table->bDex, data[col++]);
str_to_number(mob_table->bCon, data[col++]);
str_to_number(mob_table->bInt, data[col++]);
str_to_number(mob_table->dwDamageRange[0], data[col++]);
str_to_number(mob_table->dwDamageRange[1], data[col++]);
str_to_number(mob_table->dwMaxHP, data[col++]);
str_to_number(mob_table->bRegenCycle, data[col++]);
str_to_number(mob_table->bRegenPercent, data[col++]);
str_to_number(mob_table->dwExp, data[col++]);
str_to_number(mob_table->dwGoldMin, data[col++]);
str_to_number(mob_table->dwGoldMax, data[col++]);
str_to_number(mob_table->wDef, data[col++]);
str_to_number(mob_table->sAttackSpeed, data[col++]);
str_to_number(mob_table->sMovingSpeed, data[col++]);
str_to_number(mob_table->bAggresiveHPPct, data[col++]);
str_to_number(mob_table->wAggressiveSight, data[col++]);
str_to_number(mob_table->wAttackRange, data[col++]);
str_to_number(mob_table->dwPolymorphItemVnum, data[col++]);
int i;
for (i = 0; i < MOB_ENCHANTS_MAX_NUM; ++i)
str_to_number(mob_table->cEnchants[i], data[col++]);
for (i = 0; i < MOB_RESISTS_MAX_NUM; ++i)
str_to_number(mob_table->cResists[i], data[col++]);
str_to_number(mob_table->fDamMultiply, data[col++]);
str_to_number(mob_table->dwSummonVnum, data[col++]);
str_to_number(mob_table->dwDrainSP, data[col++]);
for (i = 0; i < MOB_SKILL_MAX_NUM; ++i)
{
str_to_number(mob_table->Skills[i].dwVnum, data[col++]);
str_to_number(mob_table->Skills[i].bLevel, data[col++]);
}
str_to_number(mob_table->bBerserkPoint, data[col++]);
str_to_number(mob_table->bStoneSkinPoint, data[col++]);
str_to_number(mob_table->bGodSpeedPoint, data[col++]);
str_to_number(mob_table->bDeathBlowPoint, data[col++]);
str_to_number(mob_table->bRevivePoint, data[col++]);
sys_log(1, "MOB #%-5d %-24s %-24s level: %-3u rank: %u empire: %d", mob_table->dwVnum, mob_table->szName, mob_table->szLocaleName, mob_table->bLevel, mob_table->bRank, mob_table->bEmpire);
++mob_table;
}
sort(m_vec_mobTable.begin(), m_vec_mobTable.end(), FCompareVnum());
sys_log(0, "CClientManager::InitializeMobTable:: %d mobs loaded.n", m_vec_mobTable.size());
fprintf(stderr, "CClientManager::InitializeMobTable:: %d mobs loaded\n", m_vec_mobTable.size());
return true;
}
bool CClientManager::InitializeShopTable()
{
MYSQL_ROW data;
int col;
static const char * s_szQuery =
"SELECT "
"shop.vnum, "
"shop.npc_vnum, "
"shop_item.item_vnum, "
"shop_item.count "
"FROM shop LEFT JOIN shop_item "
"ON shop.vnum = shop_item.shop_vnum ORDER BY shop.vnum, shop_item.item_vnum";
std::auto_ptr<SQLMsg> pkMsg2(CDBManager::instance().DirectQuery(s_szQuery));
// shop의 vnum은 있는데 shop_item 이 없을경우... 실패로 처리되니 주의 요망.
// 고처야할부분
SQLResult * pRes2 = pkMsg2->Get();
if (!pRes2->uiNumRows)
{
sys_err("InitializeShopTable : Table count is zero.");
return false;
}
std::map<int, TShopTable *> map_shop;
if (m_pShopTable)
{
delete [] (m_pShopTable);
m_pShopTable = NULL;
}
TShopTable * shop_table = m_pShopTable;
while ((data = mysql_fetch_row(pRes2->pSQLResult)))
{
col = 0;
int iShopVnum = 0;
str_to_number(iShopVnum, data[col++]);
if (map_shop.end() == map_shop.find(iShopVnum))
{
shop_table = new TShopTable;
memset(shop_table, 0, sizeof(TShopTable));
shop_table->dwVnum = iShopVnum;
map_shop[iShopVnum] = shop_table;
}
else
shop_table = map_shop[iShopVnum];
str_to_number(shop_table->dwNPCVnum, data[col++]);
if (!data[col]) // 아이템이 하나도 없으면 NULL이 리턴 되므로..
continue;
TShopItemTable * pItem = &shop_table->items[shop_table->byItemCount];
str_to_number(pItem->vnum, data[col++]);
str_to_number(pItem->count, data[col++]);
++shop_table->byItemCount;
}
m_pShopTable = new TShopTable[map_shop.size()];
m_iShopTableSize = map_shop.size();
typeof(map_shop.begin()) it = map_shop.begin();
int i = 0;
while (it != map_shop.end())
{
thecore_memcpy((m_pShopTable + i), (it++)->second, sizeof(TShopTable));
sys_log(0, "SHOP: #%d items: %d", (m_pShopTable + i)->dwVnum, (m_pShopTable + i)->byItemCount);
++i;
}
return true;
}
bool CClientManager::InitializeQuestItemTable()
{
using namespace std;
static const char * s_szQuery = "SELECT vnum, name, %s FROM quest_item_proto ORDER BY vnum";
char query[1024];
snprintf(query, sizeof(query), s_szQuery, g_stLocaleNameColumn.c_str());
std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query));
SQLResult * pRes = pkMsg->Get();
if (!pRes->uiNumRows)
{
sys_err("query error or no rows: %s", query);
return false;
}
MYSQL_ROW row;
while ((row = mysql_fetch_row(pRes->pSQLResult)))
{
int col = 0;
TItemTable tbl;
memset(&tbl, 0, sizeof(tbl));
str_to_number(tbl.dwVnum, row[col++]);
if (row[col])
strlcpy(tbl.szName, row[col], sizeof(tbl.szName));
col++;
if (row[col])
strlcpy(tbl.szLocaleName, row[col], sizeof(tbl.szLocaleName));
col++;
if (m_map_itemTableByVnum.find(tbl.dwVnum) != m_map_itemTableByVnum.end())
{
sys_err("QUEST_ITEM_ERROR! %lu vnum already exist! (name %s)", tbl.dwVnum, tbl.szLocaleName);
continue;
}
tbl.bType = ITEM_QUEST; // quest_item_proto 테이블에 있는 것들은 모두 ITEM_QUEST 유형
tbl.bSize = 1;
m_vec_itemTable.push_back(tbl);
}
return true;
}
bool CClientManager::InitializeItemTable()
{
char query[4096];
snprintf(query, sizeof(query),
"SELECT vnum, name, %s, type, subtype, gold, shop_buy_price, weight, size, flag, wearflag, "
"antiflag, immuneflag+0, refined_vnum, refine_set, magic_pct, socket_pct, addon_type, "
"limittype0, limitvalue0, limittype1, limitvalue1, "
"applytype0, applyvalue0, applytype1, applyvalue1, applytype2, applyvalue2, "
"value0, value1, value2, value3, value4, value5 "
"FROM item_proto%s ORDER BY vnum",
g_stLocaleNameColumn.c_str(), GetTablePostfix());
std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query));
SQLResult * pRes = pkMsg->Get();
if (!pRes->uiNumRows)
{
sys_err("Could not load item_proto. No results!");
return false;
}
sys_log(0, "ITEM_PROTO loading...");
if (!m_vec_itemTable.empty())
{
sys_log(0, "RELOAD: item_proto");
m_vec_itemTable.clear();
m_map_itemTableByVnum.clear();
}
m_vec_itemTable.resize(pRes->uiNumRows);
memset(&m_vec_itemTable[0], 0, sizeof(TItemTable) * m_vec_itemTable.size());
TItemTable * item_table = &m_vec_itemTable[0];
MYSQL_ROW data;
int col;
while ((data = mysql_fetch_row(pRes->pSQLResult)))
{
col = 0;
str_to_number(item_table->dwVnum, data[col++]);
strlcpy(item_table->szName, data[col++], sizeof(item_table->szName));
strlcpy(item_table->szLocaleName, data[col++], sizeof(item_table->szLocaleName));
str_to_number(item_table->bType, data[col++]);
str_to_number(item_table->bSubType, data[col++]);
str_to_number(item_table->dwGold, data[col++]);
str_to_number(item_table->dwShopBuyPrice, data[col++]);
str_to_number(item_table->bWeight, data[col++]);
str_to_number(item_table->bSize, data[col++]);
str_to_number(item_table->dwFlags, data[col++]);
str_to_number(item_table->dwWearFlags, data[col++]);
str_to_number(item_table->dwAntiFlags, data[col++]);
str_to_number(item_table->dwImmuneFlag, data[col++]);
str_to_number(item_table->dwRefinedVnum, data[col++]);
str_to_number(item_table->wRefineSet, data[col++]);
str_to_number(item_table->bAlterToMagicItemPct, data[col++]);
str_to_number(item_table->bGainSocketPct, data[col++]);
str_to_number(item_table->sAddonType, data[col++]);
item_table->cLimitRealTimeFirstUseIndex = -1;
item_table->cLimitTimerBasedOnWearIndex = -1;
int i;
for (i = 0; i < ITEM_LIMIT_MAX_NUM; ++i)
{
str_to_number(item_table->aLimits[i].bType, data[col++]);
str_to_number(item_table->aLimits[i].lValue, data[col++]);
if (LIMIT_REAL_TIME_START_FIRST_USE == item_table->aLimits[i].bType)
item_table->cLimitRealTimeFirstUseIndex = (char)i;
if (LIMIT_TIMER_BASED_ON_WEAR == item_table->aLimits[i].bType)
item_table->cLimitTimerBasedOnWearIndex = (char)i;
}
for (i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
{
str_to_number(item_table->aApplies[i].bType, data[col++]);
str_to_number(item_table->aApplies[i].lValue, data[col++]);
}
for (i = 0; i < ITEM_VALUES_MAX_NUM; ++i)
str_to_number(item_table->alValues[i], data[col++]);
sys_log(1, "ITEM: #%-5lu %-24s %-24s VAL: %ld %ld %ld %ld %ld %ld WEAR %lu ANTI %lu IMMUNE %lu REFINE %lu REFINE_SET %u MAGIC_PCT %u",
item_table->dwVnum,item_table->szName,item_table->szLocaleName,
item_table->alValues[0],item_table->alValues[1],item_table->alValues[2],
item_table->alValues[3],item_table->alValues[4],item_table->alValues[5],
item_table->dwWearFlags,item_table->dwAntiFlags,item_table->dwImmuneFlag,
item_table->dwRefinedVnum,item_table->wRefineSet,item_table->bAlterToMagicItemPct);
m_map_itemTableByVnum.insert(std::map<DWORD, TItemTable *>::value_type(item_table->dwVnum, item_table));
++item_table;
}
sort(m_vec_itemTable.begin(), m_vec_itemTable.end(), FCompareVnum());
sys_log(0, "CClientManager::InitializeItemTable:: %d items loaded.n", m_vec_itemTable.size());
fprintf(stderr, "CClientManager::InitializeItemTable:: %d items loaded\n", m_vec_itemTable.size());
return true;
}
bool CClientManager::InitializeSkillTable()
{
char query[4096];
snprintf(query, sizeof(query),
"SELECT dwVnum, szName, bType, bMaxLevel, dwSplashRange, "
"szPointOn, szPointPoly, szSPCostPoly, szDurationPoly, szDurationSPCostPoly, "
"szCooldownPoly, szMasterBonusPoly, setFlag+0, setAffectFlag+0, "
"szPointOn2, szPointPoly2, szDurationPoly2, setAffectFlag2+0, "
"szPointOn3, szPointPoly3, szDurationPoly3, szGrandMasterAddSPCostPoly, "
"bLevelStep, bLevelLimit, prerequisiteSkillVnum, prerequisiteSkillLevel, iMaxHit, szSplashAroundDamageAdjustPoly, eSkillType+0, dwTargetRange "
"FROM skill_proto%s ORDER BY dwVnum",
GetTablePostfix());
std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query));
SQLResult * pRes = pkMsg->Get();
if (!pRes->uiNumRows)
{
sys_err("no result from skill_proto");
return false;
}
if (!m_vec_skillTable.empty())
{
sys_log(0, "RELOAD: skill_proto");
m_vec_skillTable.clear();
}
m_vec_skillTable.reserve(pRes->uiNumRows);
MYSQL_ROW data;
int col;
while ((data = mysql_fetch_row(pRes->pSQLResult)))
{
TSkillTable t;
memset(&t, 0, sizeof(t));
col = 0;
str_to_number(t.dwVnum, data[col++]);
strlcpy(t.szName, data[col++], sizeof(t.szName));
str_to_number(t.bType, data[col++]);
str_to_number(t.bMaxLevel, data[col++]);
str_to_number(t.dwSplashRange, data[col++]);
strlcpy(t.szPointOn, data[col++], sizeof(t.szPointOn));
strlcpy(t.szPointPoly, data[col++], sizeof(t.szPointPoly));
strlcpy(t.szSPCostPoly, data[col++], sizeof(t.szSPCostPoly));
strlcpy(t.szDurationPoly, data[col++], sizeof(t.szDurationPoly));
strlcpy(t.szDurationSPCostPoly, data[col++], sizeof(t.szDurationSPCostPoly));
strlcpy(t.szCooldownPoly, data[col++], sizeof(t.szCooldownPoly));
strlcpy(t.szMasterBonusPoly, data[col++], sizeof(t.szMasterBonusPoly));
str_to_number(t.dwFlag, data[col++]);
str_to_number(t.dwAffectFlag, data[col++]);
strlcpy(t.szPointOn2, data[col++], sizeof(t.szPointOn2));
strlcpy(t.szPointPoly2, data[col++], sizeof(t.szPointPoly2));
strlcpy(t.szDurationPoly2, data[col++], sizeof(t.szDurationPoly2));
str_to_number(t.dwAffectFlag2, data[col++]);
// ADD_GRANDMASTER_SKILL
strlcpy(t.szPointOn3, data[col++], sizeof(t.szPointOn3));
strlcpy(t.szPointPoly3, data[col++], sizeof(t.szPointPoly3));
strlcpy(t.szDurationPoly3, data[col++], sizeof(t.szDurationPoly3));
strlcpy(t.szGrandMasterAddSPCostPoly, data[col++], sizeof(t.szGrandMasterAddSPCostPoly));
// END_OF_ADD_GRANDMASTER_SKILL
str_to_number(t.bLevelStep, data[col++]);
str_to_number(t.bLevelLimit, data[col++]);
str_to_number(t.preSkillVnum, data[col++]);
str_to_number(t.preSkillLevel, data[col++]);
str_to_number(t.lMaxHit, data[col++]);
strlcpy(t.szSplashAroundDamageAdjustPoly, data[col++], sizeof(t.szSplashAroundDamageAdjustPoly));
str_to_number(t.bSkillAttrType, data[col++]);
str_to_number(t.dwTargetRange, data[col++]);
sys_log(0, "SKILL: #%d %s flag %u point %s affect %u cooldown %s", t.dwVnum, t.szName, t.dwFlag, t.szPointOn, t.dwAffectFlag, t.szCooldownPoly);
m_vec_skillTable.push_back(t);
}
return true;
}
bool CClientManager::InitializeBanwordTable()
{
m_vec_banwordTable.clear();
std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery("SELECT word FROM banword"));
SQLResult * pRes = pkMsg->Get();
if (pRes->uiNumRows == 0)
return true;
MYSQL_ROW data;
while ((data = mysql_fetch_row(pRes->pSQLResult)))
{
TBanwordTable t;
if (data[0])
{
strlcpy(t.szWord, data[0], sizeof(t.szWord));
m_vec_banwordTable.push_back(t);
}
}
sys_log(0, "BANWORD: total %d", m_vec_banwordTable.size());
return true;
}
bool CClientManager::InitializeItemAttrTable()
{
char query[4096];
snprintf(query, sizeof(query),
"SELECT apply, apply+0, prob, lv1, lv2, lv3, lv4, lv5, weapon, body, wrist, foots, neck, head, shield, ear FROM item_attr%s ORDER BY apply",
GetTablePostfix());
std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query));
SQLResult * pRes = pkMsg->Get();
if (!pRes->uiNumRows)
{
sys_err("no result from item_attr");
return false;
}
if (!m_vec_itemAttrTable.empty())
{
sys_log(0, "RELOAD: item_attr");
m_vec_itemAttrTable.clear();
}
m_vec_itemAttrTable.reserve(pRes->uiNumRows);
MYSQL_ROW data;
while ((data = mysql_fetch_row(pRes->pSQLResult)))
{
TItemAttrTable t;
memset(&t, 0, sizeof(TItemAttrTable));
int col = 0;
strlcpy(t.szApply, data[col++], sizeof(t.szApply));
str_to_number(t.dwApplyIndex, data[col++]);
str_to_number(t.dwProb, data[col++]);
str_to_number(t.lValues[0], data[col++]);
str_to_number(t.lValues[1], data[col++]);
str_to_number(t.lValues[2], data[col++]);
str_to_number(t.lValues[3], data[col++]);
str_to_number(t.lValues[4], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_WEAPON], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_BODY], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_WRIST], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_FOOTS], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_NECK], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_HEAD], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_SHIELD], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_EAR], data[col++]);
sys_log(0, "ITEM_ATTR: %-20s %4lu { %3d %3d %3d %3d %3d } { %d %d %d %d %d %d %d }",
t.szApply,
t.dwProb,
t.lValues[0],
t.lValues[1],
t.lValues[2],
t.lValues[3],
t.lValues[4],
t.bMaxLevelBySet[ATTRIBUTE_SET_WEAPON],
t.bMaxLevelBySet[ATTRIBUTE_SET_BODY],
t.bMaxLevelBySet[ATTRIBUTE_SET_WRIST],
t.bMaxLevelBySet[ATTRIBUTE_SET_FOOTS],
t.bMaxLevelBySet[ATTRIBUTE_SET_NECK],
t.bMaxLevelBySet[ATTRIBUTE_SET_HEAD],
t.bMaxLevelBySet[ATTRIBUTE_SET_SHIELD],
t.bMaxLevelBySet[ATTRIBUTE_SET_EAR]);
m_vec_itemAttrTable.push_back(t);
}
return true;
}
bool CClientManager::InitializeItemRareTable()
{
char query[4096];
snprintf(query, sizeof(query),
"SELECT apply, apply+0, prob, lv1, lv2, lv3, lv4, lv5, weapon, body, wrist, foots, neck, head, shield, ear FROM item_attr_rare%s ORDER BY apply",
GetTablePostfix());
std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query));
SQLResult * pRes = pkMsg->Get();
if (!pRes->uiNumRows)
{
sys_err("no result from item_attr_rare");
return false;
}
if (!m_vec_itemRareTable.empty())
{
sys_log(0, "RELOAD: item_attr_rare");
m_vec_itemRareTable.clear();
}
m_vec_itemRareTable.reserve(pRes->uiNumRows);
MYSQL_ROW data;
while ((data = mysql_fetch_row(pRes->pSQLResult)))
{
TItemAttrTable t;
memset(&t, 0, sizeof(TItemAttrTable));
int col = 0;
strlcpy(t.szApply, data[col++], sizeof(t.szApply));
str_to_number(t.dwApplyIndex, data[col++]);
str_to_number(t.dwProb, data[col++]);
str_to_number(t.lValues[0], data[col++]);
str_to_number(t.lValues[1], data[col++]);
str_to_number(t.lValues[2], data[col++]);
str_to_number(t.lValues[3], data[col++]);
str_to_number(t.lValues[4], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_WEAPON], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_BODY], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_WRIST], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_FOOTS], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_NECK], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_HEAD], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_SHIELD], data[col++]);
str_to_number(t.bMaxLevelBySet[ATTRIBUTE_SET_EAR], data[col++]);
sys_log(0, "ITEM_RARE: %-20s %4lu { %3d %3d %3d %3d %3d } { %d %d %d %d %d %d %d }",
t.szApply,
t.dwProb,
t.lValues[0],
t.lValues[1],
t.lValues[2],
t.lValues[3],
t.lValues[4],
t.bMaxLevelBySet[ATTRIBUTE_SET_WEAPON],
t.bMaxLevelBySet[ATTRIBUTE_SET_BODY],
t.bMaxLevelBySet[ATTRIBUTE_SET_WRIST],
t.bMaxLevelBySet[ATTRIBUTE_SET_FOOTS],
t.bMaxLevelBySet[ATTRIBUTE_SET_NECK],
t.bMaxLevelBySet[ATTRIBUTE_SET_HEAD],
t.bMaxLevelBySet[ATTRIBUTE_SET_SHIELD],
t.bMaxLevelBySet[ATTRIBUTE_SET_EAR]);
m_vec_itemRareTable.push_back(t);
}
return true;
}
bool CClientManager::InitializeLandTable()
{
using namespace building;
char query[4096];
snprintf(query, sizeof(query),
"SELECT id, map_index, x, y, width, height, guild_id, guild_level_limit, price "
"FROM land%s WHERE enable='YES' ORDER BY id",
GetTablePostfix());
std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query));
SQLResult * pRes = pkMsg->Get();
if (!m_vec_kLandTable.empty())
{
sys_log(0, "RELOAD: land");
m_vec_kLandTable.clear();
}
m_vec_kLandTable.reserve(pRes->uiNumRows);
MYSQL_ROW data;
if (pRes->uiNumRows > 0)
while ((data = mysql_fetch_row(pRes->pSQLResult)))
{
TLand t;
memset(&t, 0, sizeof(t));
int col = 0;
str_to_number(t.dwID, data[col++]);
str_to_number(t.lMapIndex, data[col++]);
str_to_number(t.x, data[col++]);
str_to_number(t.y, data[col++]);
str_to_number(t.width, data[col++]);
str_to_number(t.height, data[col++]);
str_to_number(t.dwGuildID, data[col++]);
str_to_number(t.bGuildLevelLimit, data[col++]);
str_to_number(t.dwPrice, data[col++]);
sys_log(0, "LAND: %lu map %-4ld %7ldx%-7ld w %-4ld h %-4ld", t.dwID, t.lMapIndex, t.x, t.y, t.width, t.height);
m_vec_kLandTable.push_back(t);
}
return true;
}
void parse_pair_number_string(const char * c_pszString, std::vector<std::pair<int, int> > & vec)
{
// format: 10,1/20,3/300,50
const char * t = c_pszString;
const char * p = strchr(t, '/');
std::pair<int, int> k;
char szNum[32 + 1];
char * comma;
while (p)
{
if (isnhdigit(*t))
{
strlcpy(szNum, t, MIN(sizeof(szNum), (p-t)+1));
comma = strchr(szNum, ',');
if (comma)
{
*comma = '\0';
str_to_number(k.second, comma+1);
}
else
k.second = 0;
str_to_number(k.first, szNum);
vec.push_back(k);
}
t = p + 1;
p = strchr(t, '/');
}
if (isnhdigit(*t))
{
strlcpy(szNum, t, sizeof(szNum));
comma = strchr(const_cast<char*>(t), ',');
if (comma)
{
*comma = '\0';
str_to_number(k.second, comma+1);
}
else
k.second = 0;
str_to_number(k.first, szNum);
vec.push_back(k);
}
}
bool CClientManager::InitializeObjectProto()
{
using namespace building;
char query[4096];
snprintf(query, sizeof(query),
"SELECT vnum, price, materials, upgrade_vnum, upgrade_limit_time, life, reg_1, reg_2, reg_3, reg_4, npc, group_vnum, dependent_group "
"FROM object_proto%s ORDER BY vnum",
GetTablePostfix());
std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query));
SQLResult * pRes = pkMsg->Get();
if (!m_vec_kObjectProto.empty())
{
sys_log(0, "RELOAD: object_proto");
m_vec_kObjectProto.clear();
}
m_vec_kObjectProto.reserve(MAX(0, pRes->uiNumRows));
MYSQL_ROW data;
if (pRes->uiNumRows > 0)
while ((data = mysql_fetch_row(pRes->pSQLResult)))
{
TObjectProto t;
memset(&t, 0, sizeof(t));
int col = 0;
str_to_number(t.dwVnum, data[col++]);
str_to_number(t.dwPrice, data[col++]);
std::vector<std::pair<int, int> > vec;
parse_pair_number_string(data[col++], vec);
for (unsigned int i = 0; i < OBJECT_MATERIAL_MAX_NUM && i < vec.size(); ++i)
{
std::pair<int, int> & r = vec[i];
t.kMaterials[i].dwItemVnum = r.first;
t.kMaterials[i].dwCount = r.second;
}
str_to_number(t.dwUpgradeVnum, data[col++]);
str_to_number(t.dwUpgradeLimitTime, data[col++]);
str_to_number(t.lLife, data[col++]);
str_to_number(t.lRegion[0], data[col++]);
str_to_number(t.lRegion[1], data[col++]);
str_to_number(t.lRegion[2], data[col++]);
str_to_number(t.lRegion[3], data[col++]);
// ADD_BUILDING_NPC
str_to_number(t.dwNPCVnum, data[col++]);
str_to_number(t.dwGroupVnum, data[col++]);
str_to_number(t.dwDependOnGroupVnum, data[col++]);
t.lNPCX = 0;
t.lNPCY = MAX(t.lRegion[1], t.lRegion[3])+300;
// END_OF_ADD_BUILDING_NPC
sys_log(0, "OBJ_PROTO: vnum %lu price %lu mat %lu %lu",
t.dwVnum, t.dwPrice, t.kMaterials[0].dwItemVnum, t.kMaterials[0].dwCount);
m_vec_kObjectProto.push_back(t);
}
return true;
}
bool CClientManager::InitializeObjectTable()
{
using namespace building;
char query[4096];
snprintf(query, sizeof(query), "SELECT id, land_id, vnum, map_index, x, y, x_rot, y_rot, z_rot, life FROM object%s ORDER BY id", GetTablePostfix());
std::auto_ptr<SQLMsg> pkMsg(CDBManager::instance().DirectQuery(query));
SQLResult * pRes = pkMsg->Get();
if (!m_map_pkObjectTable.empty())
{
sys_log(0, "RELOAD: object");
m_map_pkObjectTable.clear();
}
MYSQL_ROW data;
if (pRes->uiNumRows > 0)
while ((data = mysql_fetch_row(pRes->pSQLResult)))
{
TObject * k = new TObject;
memset(k, 0, sizeof(TObject));
int col = 0;
str_to_number(k->dwID, data[col++]);
str_to_number(k->dwLandID, data[col++]);
str_to_number(k->dwVnum, data[col++]);
str_to_number(k->lMapIndex, data[col++]);
str_to_number(k->x, data[col++]);
str_to_number(k->y, data[col++]);
str_to_number(k->xRot, data[col++]);
str_to_number(k->yRot, data[col++]);
str_to_number(k->zRot, data[col++]);
str_to_number(k->lLife, data[col++]);
sys_log(0, "OBJ: %lu vnum %lu map %-4ld %7ldx%-7ld life %ld",
k->dwID, k->dwVnum, k->lMapIndex, k->x, k->y, k->lLife);
m_map_pkObjectTable.insert(std::make_pair(k->dwID, k));
}
return true;
}
bool CClientManager::InitializeMonarch()
{
CMonarch::instance().LoadMonarch();
return true;
}
Thanks