Add project files.

This commit is contained in:
2022-03-05 12:44:06 +02:00
parent 453a74459f
commit f4f90b2533
517 changed files with 195610 additions and 0 deletions

37
db/CMakeLists.txt Normal file
View File

@ -0,0 +1,37 @@
cmake_minimum_required(VERSION 3.8)
project(db CXX)
file(GLOB_RECURSE sources
src/*.cpp src/*.h
)
include_directories(${PROJECT_BINARY_DIR}/src/)
include_directories(src/)
# Find dependencies
find_package(libmysql REQUIRED)
find_package(Boost REQUIRED)
add_executable(${PROJECT_NAME} ${sources})
# Link dependencies if found
if (libmysql_FOUND)
target_link_libraries (${PROJECT_NAME} ${MYSQL_LIBRARIES})
endif (libmysql_FOUND)
if (Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries (${PROJECT_NAME} ${Boost_LIBRARIES} ${Boost_SYSTEM_LIBRARY})
endif (Boost_FOUND)
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
# Pthreads
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package (Threads REQUIRED)
target_link_libraries (${PROJECT_NAME} Threads::Threads)
endif (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
target_link_libraries(${PROJECT_NAME} libpoly libsql libthecore)

719
db/src/AuctionManager.cpp Normal file
View File

@ -0,0 +1,719 @@
#include "stdafx.h"
#ifdef __AUCTION__
#include "DBManager.h"
#include "Peer.h"
#include "AuctionManager.h"
void MyBidBoard::Boot (CPeer* peer)
{
peer->EncodeWORD(sizeof(DWORD) + sizeof(DWORD) + sizeof(int));
peer->EncodeWORD(Size());
for (TMyBidBoard::iterator pc_it = pc_map.begin(); pc_it != pc_map.end(); pc_it++)
{
TItemMap* item_map = pc_it->second;
for (TItemMap::iterator it = item_map->begin(); it != item_map->end(); it++)
{
peer->Encode(&(pc_it->first), sizeof(DWORD));
peer->Encode(&(it->first), sizeof(DWORD));
peer->Encode(&(it->second), sizeof(int));
}
}
}
size_t MyBidBoard::Size ()
{
size_t size = 0;
for (TMyBidBoard::iterator it = pc_map.begin(); it != pc_map.end(); it++)
{
size += it->second->size();
}
return size;
}
int MyBidBoard::GetMoney (DWORD player_id, DWORD item_id)
{
TMyBidBoard::iterator pc_it = pc_map.find (player_id);
if (pc_it == pc_map.end())
{
return -1;
}
TItemMap* item_map = pc_it->second;
TItemMap::iterator it = item_map->find (item_id);
if (it == item_map->end())
return -1;
else
return it->second;
}
bool MyBidBoard::Delete (DWORD player_id, DWORD item_id)
{
TMyBidBoard::iterator pc_it = pc_map.find (player_id);
if (pc_it == pc_map.end())
{
return false;
}
TItemMap* item_map = pc_it->second;
TItemMap::iterator it = item_map->find (item_id);
if (it == item_map->end())
return false;
else
{
item_map->erase(it);
}
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "DELETE FROM my_bid WHERE player_id = %d and item_id = %d", player_id, item_id);
CDBManager::instance().AsyncQuery(szQuery);
return true;
}
void MyBidBoard::Insert (DWORD player_id, DWORD item_id, int money)
{
TMyBidBoard::iterator pc_it = pc_map.find (player_id);
TItemMap* item_map;
if (pc_it == pc_map.end())
{
item_map = new TItemMap();
pc_map.insert (TMyBidBoard::value_type (player_id, item_map));
}
else
item_map = pc_it->second;
TItemMap::iterator it = item_map->find (item_id);
if (it == item_map->end())
{
item_map->insert (TItemMap::value_type (item_id, money));
}
else
{
it->second = money;
}
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "REPLACE INTO my_bid VALUES (%d, %d, %d)", player_id, item_id, money);
CDBManager::instance().AsyncQuery(szQuery);
}
AuctionManager::AuctionManager()
{
}
AuctionManager::~AuctionManager()
{
}
void AuctionManager::Initialize()
{ auction_item_cache_map.clear();
LoadAuctionItem();
LoadAuctionInfo();
LoadSaleInfo();
LoadWishInfo();
LoadMyBidInfo();
}
void AuctionManager::LoadAuctionItem()
{
char szQuery[512];
snprintf(szQuery, sizeof(szQuery),
"SELECT id, owner_id, count, vnum, socket0, socket1, socket2, "
"attrtype0, attrvalue0, "
"attrtype1, attrvalue1, "
"attrtype2, attrvalue2, "
"attrtype3, attrvalue3, "
"attrtype4, attrvalue4, "
"attrtype5, attrvalue5, "
"attrtype6, attrvalue6 "
"FROM item WHERE window = 'AUCTION'");
SQLMsg *msg = CDBManager::instance().DirectQuery(szQuery);
MYSQL_RES *res = msg->Get()->pSQLResult;
if (!res)
{
return;
}
int rows;
if ((rows = mysql_num_rows(res)) <= 0) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
return;
}
for (int i = 0; i < rows; ++i)
{
MYSQL_ROW row = mysql_fetch_row(res);
TPlayerItem item;
int cur = 0;
str_to_number(item.id, row[cur++]);
str_to_number(item.owner, row[cur++]);
item.window = AUCTION;
str_to_number(item.count, row[cur++]);
str_to_number(item.vnum, row[cur++]);
str_to_number(item.alSockets[0], row[cur++]);
str_to_number(item.alSockets[1], row[cur++]);
str_to_number(item.alSockets[2], row[cur++]);
for (int j = 0; j < ITEM_ATTRIBUTE_MAX_NUM; j++)
{
str_to_number(item.aAttr[j].bType, row[cur++]);
str_to_number(item.aAttr[j].sValue, row[cur++]);
}
InsertItemCache(&item, true);
}
return;
}
void AuctionManager::LoadAuctionInfo()
{
char szQuery[512];
snprintf(szQuery, sizeof(szQuery),
"select * from auction");
SQLMsg *msg = CDBManager::instance().DirectQuery(szQuery);
MYSQL_RES *res = msg->Get()->pSQLResult;
if (!res)
{
return;
}
int rows;
if ((rows = mysql_num_rows(res)) <= 0) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
return;
}
for (int i = 0; i < rows; ++i)
{
MYSQL_ROW row = mysql_fetch_row(res);
TAuctionItemInfo auctionItemInfo;
int cur = 0;
str_to_number(auctionItemInfo.item_num, row[cur++]);
str_to_number(auctionItemInfo.offer_price, row[cur++]);
str_to_number(auctionItemInfo.price, row[cur++]);
str_to_number(auctionItemInfo.offer_id, row[cur++]);
thecore_memcpy (auctionItemInfo.shown_name, (char*)row[cur], strlen((char*)row[cur]) +1);
cur++;
str_to_number(auctionItemInfo.empire, row[cur++]);
str_to_number(auctionItemInfo.expired_time, row[cur++]);
str_to_number(auctionItemInfo.item_id, row[cur++]);
str_to_number(auctionItemInfo.bidder_id, row[cur++]);
InsertAuctionItemInfoCache(&auctionItemInfo, true);
}
return;
}
void AuctionManager::LoadSaleInfo()
{
char szQuery[512];
snprintf(szQuery, sizeof(szQuery),
"select * from sale");
SQLMsg *msg = CDBManager::instance().DirectQuery(szQuery);
MYSQL_RES *res = msg->Get()->pSQLResult;
if (!res)
{
return;
}
int rows;
if ((rows = mysql_num_rows(res)) <= 0) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
return;
}
for (int i = 0; i < rows; ++i)
{
MYSQL_ROW row = mysql_fetch_row(res);
TSaleItemInfo saleItemInfo;
int cur = 0;
str_to_number(saleItemInfo.item_num, row[cur++]);
str_to_number(saleItemInfo.offer_price, row[cur++]);
str_to_number(saleItemInfo.price, row[cur++]);
str_to_number(saleItemInfo.offer_id, row[cur++]);
thecore_memcpy (saleItemInfo.shown_name, (char*)row[cur], strlen((char*)row[cur]) +1);
cur++;
str_to_number(saleItemInfo.empire, row[cur++]);
str_to_number(saleItemInfo.expired_time, row[cur++]);
str_to_number(saleItemInfo.item_id, row[cur++]);
str_to_number(saleItemInfo.wisher_id, row[cur++]);
InsertSaleItemInfoCache(&saleItemInfo, true);
}
return;
}
void AuctionManager::LoadWishInfo()
{
char szQuery[512];
snprintf(szQuery, sizeof(szQuery),
"select * from wish");
SQLMsg *msg = CDBManager::instance().DirectQuery(szQuery);
MYSQL_RES *res = msg->Get()->pSQLResult;
if (!res)
{
return;
}
int rows;
if ((rows = mysql_num_rows(res)) <= 0) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
return;
}
for (int i = 0; i < rows; ++i)
{
MYSQL_ROW row = mysql_fetch_row(res);
TWishItemInfo wishItemInfo;
int cur = 0;
str_to_number(wishItemInfo.item_num, row[cur++]);
str_to_number(wishItemInfo.offer_price, row[cur++]);
str_to_number(wishItemInfo.price, row[cur++]);
str_to_number(wishItemInfo.offer_id, row[cur++]);
thecore_memcpy (wishItemInfo.shown_name, (char*)row[cur], strlen((char*)row[cur]) +1);
cur++;
str_to_number(wishItemInfo.empire, row[cur++]);
str_to_number(wishItemInfo.expired_time, row[cur++]);
InsertWishItemInfoCache(&wishItemInfo, true);
}
return;
}
void AuctionManager::LoadMyBidInfo ()
{
char szQuery[512];
snprintf(szQuery, sizeof(szQuery),
"select * from my_bid");
SQLMsg *msg = CDBManager::instance().DirectQuery(szQuery);
MYSQL_RES *res = msg->Get()->pSQLResult;
if (!res)
{
return;
}
int rows;
if ((rows = mysql_num_rows(res)) <= 0) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
{
return;
}
for (int i = 0; i < rows; ++i)
{
MYSQL_ROW row = mysql_fetch_row(res);
int cur = 0;
DWORD player_id;
DWORD item_id;
int money;
str_to_number(player_id, row[cur++]);
str_to_number(item_id, row[cur++]);
str_to_number(money, row[cur++]);
InsertMyBid (player_id, item_id, money);
}
return;
}
inline CItemCache* AuctionManager::GetItemCache(DWORD item_id)
{
TItemCacheMap::iterator it = auction_item_cache_map.find (item_id);
if (it == auction_item_cache_map.end())
return NULL;
else
return it->second;
}
void AuctionManager::Boot(CPeer* peer)
{
peer->EncodeWORD(sizeof(TPlayerItem));
peer->EncodeWORD(auction_item_cache_map.size());
itertype(auction_item_cache_map) auction_item_cache_map_it = auction_item_cache_map.begin();
while (auction_item_cache_map_it != auction_item_cache_map.end())
peer->Encode((auction_item_cache_map_it++)->second->Get(), sizeof(TPlayerItem));
Auction.Boot(peer);
Sale.Boot(peer);
Wish.Boot(peer);
MyBid.Boot(peer);
}
bool AuctionManager::InsertItemCache(CItemCache *item_cache, bool bSkipQuery)
{
CItemCache* c = GetItemCache (item_cache->Get(false)->id);
if (c != NULL)
{
return false;
}
auction_item_cache_map.insert(TItemCacheMap::value_type(item_cache->Get(true)->id, item_cache));
item_cache->OnFlush();
return true;
}
bool AuctionManager::InsertItemCache(TPlayerItem * pNew, bool bSkipQuery)
{
CItemCache* c = GetItemCache (pNew->id);
if (c != NULL)
{
return false;
}
c = new CItemCache();
c->Put(pNew, bSkipQuery);
auction_item_cache_map.insert(TItemCacheMap::value_type(pNew->id, c));
c->Flush();
return true;
}
bool AuctionManager::DeleteItemCache(DWORD item_id)
{
CItemCache* c = GetItemCache (item_id);
if (c == NULL)
{
return false;
}
c->Delete();
return true;
}
AuctionResult AuctionManager::EnrollInAuction(CItemCache* item_cache, TAuctionItemInfo &item_info)
{
CItemCache* c = GetItemCache (item_info.item_id);
if (c != NULL)
{
sys_err ("item id : %d is already in AuctionManager", item_info.item_id);
return AUCTION_FAIL;
}
if (!Auction.InsertItemInfo (&item_info))
{
sys_err ("item id : %d is already in AuctionBoard", item_info.item_id);
return AUCTION_FAIL;
}
item_cache->Get()->window = AUCTION;
item_cache->Get()->pos = 9999999;
InsertItemCache (item_cache);
return AUCTION_SUCCESS;
}
AuctionResult AuctionManager::EnrollInSale(CItemCache* item_cache, TSaleItemInfo &item_info)
{
CItemCache* c = GetItemCache (item_info.item_id);
if (c != NULL)
{
sys_err ("item id : %d is already in AuctionManager", item_info.item_id);
return AUCTION_FAIL;
}
if (!Wish.GetItemInfoCache (WishBoard::Key (item_info.item_num, item_info.wisher_id)))
{
sys_err ("item_num : %d, wisher_id : %d is not in wish auction.", item_info.item_num, item_info.wisher_id);
return AUCTION_FAIL;
}
if (!Sale.InsertItemInfo (&item_info))
{
sys_err ("item id : %d is already in SaleBoard", item_info.item_id);
return AUCTION_FAIL;
}
item_cache->Get()->window = AUCTION;
item_cache->Get()->pos = 999999;
InsertItemCache (item_cache);
return AUCTION_SUCCESS;
}
AuctionResult AuctionManager::EnrollInWish(TWishItemInfo &item_info)
{
if (!Wish.InsertItemInfo (&item_info))
{
sys_err ("wisher_id : %d, item_num : %d is already in WishBoard", item_info.offer_id, item_info.item_num);
return AUCTION_FAIL;
}
return AUCTION_SUCCESS;
}
AuctionResult AuctionManager::Bid(DWORD bidder_id, const char* bidder_name, DWORD item_id, DWORD bid_price)
{
CItemCache* c = GetItemCache (item_id);
if (c == NULL)
{
sys_err ("item id : %d does not exist in auction.", item_id);
return AUCTION_FAIL;
}
if (MyBid.GetMoney (bidder_id, item_id) != 0)
{
return AUCTION_ALREADY_IN;
}
CAuctionItemInfoCache* item_cache = Auction.GetItemInfoCache(item_id);
TAuctionItemInfo* item_info = item_cache->Get(false);
if (item_info->is_expired())
{
return AUCTION_EXPIRED;
}
if ((double)bid_price < (double)item_info->get_bid_price() * 1.05)
{
return AUCTION_NOT_ENOUGH_MONEY;
}
item_info->set_bid_price(bid_price);
item_info->bidder_id = bidder_id;
item_info->set_bidder_name (bidder_name);
item_cache->OnFlush();
InsertMyBid (bidder_id, item_id, bid_price);
return AUCTION_SUCCESS;
}
AuctionResult AuctionManager::Impur(DWORD purchaser_id, const char* purchaser_name, DWORD item_id)
{
CItemCache* c = GetItemCache (item_id);
if (c == NULL)
{
sys_err ("item id : %d does not exist in auction.", item_id);
return AUCTION_FAIL;
}
CAuctionItemInfoCache* item_cache = Auction.GetItemInfoCache(item_id);
TAuctionItemInfo* item_info = item_cache->Get(false);
if (item_info->is_expired())
{
return AUCTION_EXPIRED;
}
// <20><20>ع<EFBFBD><D8B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD>, <20><><EFBFBD>Ŵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
item_info->expired_time = 0;
item_info->bidder_id = purchaser_id;
item_info->set_bidder_name (purchaser_name);
item_info->set_bid_price (item_info->get_impur_price());
item_cache->OnFlush();
return AUCTION_SUCCESS;
}
AuctionResult AuctionManager::GetAuctionedItem (DWORD actor_id, DWORD item_id, TPlayerItem& item)
{
CItemCache* c = GetItemCache (item_id);
if (c == NULL)
{
sys_err ("item id : %d does not exist in auction.", item_id);
return AUCTION_FAIL;
}
CAuctionItemInfoCache* item_info_cache = Auction.GetItemInfoCache(item_id);
if (item_info_cache == NULL)
{
sys_err ("how can this accident happen?");
return AUCTION_FAIL;
}
TAuctionItemInfo* item_info = item_info_cache->Get(false);
if (!item_info->is_expired())
{
return AUCTION_NOT_EXPIRED;
}
thecore_memcpy(&item, c->Get(), sizeof(TPlayerItem));
return AUCTION_SUCCESS;
}
AuctionResult AuctionManager::BuySoldItem (DWORD actor_id, DWORD item_id, TPlayerItem& item)
{
CItemCache* c = GetItemCache (item_id);
if (c == NULL)
{
sys_err ("item id : %d does not exist in auction.", item_id);
return AUCTION_FAIL;
}
CSaleItemInfoCache* item_info_cache = Sale.GetItemInfoCache(item_id);
if (item_info_cache == NULL)
{
sys_err ("how can this accident happen?");
return AUCTION_FAIL;
}
TSaleItemInfo* item_info = item_info_cache->Get(false);
thecore_memcpy(&item, c->Get(), sizeof(TPlayerItem));
return AUCTION_SUCCESS;
}
AuctionResult AuctionManager::CancelAuction (DWORD actor_id, DWORD item_id, TPlayerItem& item)
{
CItemCache* c = GetItemCache (item_id);
if (c == NULL)
{
sys_err ("item id : %d does not exist in auction.", item_id);
return AUCTION_FAIL;
}
CAuctionItemInfoCache* item_info_cache = Auction.GetItemInfoCache(item_id);
if (item_info_cache == NULL)
{
sys_err ("how can this accident happen?");
return AUCTION_FAIL;
}
TAuctionItemInfo* item_info = item_info_cache->Get(false);
thecore_memcpy(&item, c->Get(), sizeof(TPlayerItem));
return AUCTION_SUCCESS;
}
AuctionResult AuctionManager::CancelWish (DWORD actor_id, DWORD item_num)
{
if (!Wish.DeleteItemInfoCache (WishBoard::Key (actor_id, item_num)))
{
return AUCTION_FAIL;
}
else
{
return AUCTION_SUCCESS;
}
}
AuctionResult AuctionManager::CancelSale (DWORD actor_id, DWORD item_id, TPlayerItem& item)
{
CItemCache* c = GetItemCache (item_id);
if (c == NULL)
{
sys_err ("item id : %d does not exist in auction.", item_id);
return AUCTION_FAIL;
}
CSaleItemInfoCache* item_info_cache = Sale.GetItemInfoCache(item_id);
if (item_info_cache == NULL)
{
sys_err ("how can this accident happen?");
return AUCTION_FAIL;
}
TSaleItemInfo* item_info = item_info_cache->Get(false);
thecore_memcpy(&item, c->Get(), sizeof(TPlayerItem));
return AUCTION_SUCCESS;
}
AuctionResult AuctionManager::DeleteAuctionItem (DWORD actor_id, DWORD item_id)
{
if (DeleteItemCache (item_id) == false)
{
sys_err ("item id : %d does not exist in auction.", item_id);
return AUCTION_FAIL;
}
if (Auction.DeleteItemInfoCache (item_id) == NULL)
{
sys_err ("how can this accident happen?");
return AUCTION_FAIL;
}
return AUCTION_SUCCESS;
}
AuctionResult AuctionManager::DeleteSaleItem (DWORD actor_id, DWORD item_id)
{
if (DeleteItemCache (item_id) == false)
{
sys_err ("item id : %d does not exist in auction.", item_id);
return AUCTION_FAIL;
}
if (Sale.DeleteItemInfoCache (item_id) == NULL)
{
sys_err ("how can this accident happen?");
return AUCTION_FAIL;
}
return AUCTION_SUCCESS;
}
AuctionResult AuctionManager::ReBid(DWORD bidder_id, const char* bidder_name, DWORD item_id, DWORD bid_price)
{
CItemCache* c = GetItemCache (item_id);
if (c == NULL)
{
sys_err ("item id : %d does not exist in auction.", item_id);
return AUCTION_FAIL;
}
int money = MyBid.GetMoney (bidder_id, item_id);
if (money == -1)
{
return AUCTION_NOT_IN;
}
CAuctionItemInfoCache* item_cache = Auction.GetItemInfoCache(item_id);
TAuctionItemInfo* item_info = item_cache->Get(false);
if (item_info->is_expired())
{
return AUCTION_EXPIRED;
}
if ((double)(bid_price + money) < (double)item_info->get_bid_price() * 1.05)
{
return AUCTION_NOT_ENOUGH_MONEY;
}
item_info->set_bid_price(bid_price + money);
item_info->bidder_id = bidder_id;
item_info->set_bidder_name (bidder_name);
item_cache->OnFlush();
InsertMyBid (bidder_id, item_id, money + bid_price);
return AUCTION_SUCCESS;
}
AuctionResult AuctionManager::BidCancel (DWORD bidder_id, DWORD item_id)
{
if (MyBid.Delete (bidder_id, item_id))
{
return AUCTION_SUCCESS;
}
else
{
return AUCTION_NOT_IN;
}
}
#endif

370
db/src/AuctionManager.h Normal file
View File

@ -0,0 +1,370 @@
#ifdef __AUCTION__
#ifndef __INC_AUCTION_MANAGER_H__
#define __INC_AUCTION_MANAGER_H__
#include <boost/unordered_map.hpp>
#include "Cache.h"
#include "../../common/auction_table.h"
class CItemCache;
class CAuctionItemInfoCache;
class CSaleItemInfoCache;
class CWishItemInfoCache;
template<>
class hash<std::pair <DWORD, DWORD> >
{ // hash functor
public:
typedef std::pair <DWORD, DWORD> _Kty;
size_t operator()(const _Kty& _Keyval) const
{ // hash _Keyval to size_t value by pseudorandomizing transform
ldiv_t _Qrem = ldiv((size_t)_Keyval.first + (size_t)_Keyval.second, 127773);
_Qrem.rem = 16807 * _Qrem.rem - 2836 * _Qrem.quot;
if (_Qrem.rem < 0)
_Qrem.rem += 2147483647;
return ((size_t)_Qrem.rem);
}
};
class AuctionBoard
{
public:
typedef DWORD Key;
typedef CAuctionItemInfoCache ItemInfoCache;
typedef TAuctionItemInfo ItemInfo;
public:
AuctionBoard() {}
~AuctionBoard() {}
void Boot(CPeer* peer)
{
peer->EncodeWORD(sizeof(ItemInfo));
peer->EncodeWORD(item_cache_map.size());
TItemInfoCacheMap::iterator it = item_cache_map.begin();
while (it != item_cache_map.end())
peer->Encode((it++)->second->Get(), sizeof(ItemInfo));
}
size_t Size()
{
return item_cache_map.size();
}
ItemInfoCache* GetItemInfoCache (Key key)
{
TItemInfoCacheMap::iterator it = item_cache_map.find (key);
if (it == item_cache_map.end())
return NULL;
else
return it->second;
}
bool DeleteItemInfoCache (Key key)
{
TItemInfoCacheMap::iterator it = item_cache_map.find (key);
if (it == item_cache_map.end())
return false;
else
{
it->second->Delete();
item_cache_map.erase(it);
return true;
}
}
bool InsertItemInfo (ItemInfo *pNew, bool bSkipQuery = false)
{
ItemInfoCache* c = GetItemInfoCache (Key (pNew->item_id));
if (c != NULL)
{
return false;
}
c = new ItemInfoCache();
c->Put(pNew, bSkipQuery);
item_cache_map.insert(TItemInfoCacheMap::value_type(pNew->item_id, c));
c->Flush();
return true;
}
private:
typedef boost::unordered_map <Key, ItemInfoCache *> TItemInfoCacheMap;
TItemInfoCacheMap item_cache_map;
};
class SaleBoard
{
public:
typedef DWORD Key;
typedef CSaleItemInfoCache ItemInfoCache;
typedef TSaleItemInfo ItemInfo;
SaleBoard() {}
~SaleBoard() {}
void Boot(CPeer* peer)
{
peer->EncodeWORD(sizeof(ItemInfo));
peer->EncodeWORD(item_cache_map.size());
TItemInfoCacheMap::iterator it = item_cache_map.begin();
while (it != item_cache_map.end())
peer->Encode((it++)->second->Get(), sizeof(ItemInfo));
}
size_t Size()
{
return item_cache_map.size();
}
ItemInfoCache* GetItemInfoCache (Key key)
{
TItemInfoCacheMap::iterator it = item_cache_map.find (key);
if (it == item_cache_map.end())
return NULL;
else
return it->second;
}
bool DeleteItemInfoCache (Key key)
{
TItemInfoCacheMap::iterator it = item_cache_map.find (key);
if (it == item_cache_map.end())
return false;
else
{
it->second->Delete();
item_cache_map.erase(it);
return true;
}
}
bool InsertItemInfo (ItemInfo *pNew, bool bSkipQuery = false)
{
ItemInfoCache* c = GetItemInfoCache (Key (pNew->item_id));
if (c != NULL)
{
return false;
}
c = new ItemInfoCache();
c->Put(pNew, bSkipQuery);
item_cache_map.insert(TItemInfoCacheMap::value_type(pNew->item_id, c));
c->Flush();
return true;
}
private:
typedef boost::unordered_map <Key, ItemInfoCache *> TItemInfoCacheMap;
TItemInfoCacheMap item_cache_map;
};
class WishBoard
{
public:
typedef std::pair <DWORD, DWORD> Key;
typedef CWishItemInfoCache ItemInfoCache;
typedef TWishItemInfo ItemInfo;
WishBoard() {}
virtual ~WishBoard() {}
void Boot(CPeer* peer)
{
peer->EncodeWORD(sizeof(ItemInfo));
peer->EncodeWORD(item_cache_map.size());
TItemInfoCacheMap::iterator it = item_cache_map.begin();
while (it != item_cache_map.end())
peer->Encode((it++)->second->Get(), sizeof(ItemInfo));
}
size_t Size()
{
return item_cache_map.size();
}
ItemInfoCache* GetItemInfoCache (Key key)
{
TItemInfoCacheMap::iterator it = item_cache_map.find (key);
if (it == item_cache_map.end())
return NULL;
else
return it->second;
}
bool DeleteItemInfoCache (Key key)
{
TItemInfoCacheMap::iterator it = item_cache_map.find (key);
if (it == item_cache_map.end())
return false;
else
{
it->second->Delete();
item_cache_map.erase(it);
return true;
}
}
bool InsertItemInfo (ItemInfo *pNew, bool bSkipQuery = false)
{
ItemInfoCache* c = GetItemInfoCache (Key (pNew->item_num, pNew->offer_id));
if (c != NULL)
{
return false;
}
c = new ItemInfoCache();
c->Put(pNew, bSkipQuery);
item_cache_map.insert(TItemInfoCacheMap::value_type(Key (pNew->item_num, pNew->offer_id), c));
c->Flush();
return true;
}
private:
typedef boost::unordered_map <Key, ItemInfoCache *> TItemInfoCacheMap;
TItemInfoCacheMap item_cache_map;
};
// pc<70><63> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD> <20><><EFBFBD>Ÿ<EFBFBD> <20><><EFBFBD><EFBFBD>.
class MyBidBoard
{
public:
MyBidBoard() {}
~MyBidBoard() {}
void Boot(CPeer* peer);
size_t Size();
int GetMoney (DWORD player_id, DWORD item_id);
bool Delete (DWORD player_id, DWORD item_id);
// <20>̹<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
void Insert (DWORD player_id, DWORD item_id, int money);
private:
typedef std::map <DWORD, int> TItemMap;
typedef boost::unordered_map <DWORD, TItemMap*> TMyBidBoard;
TMyBidBoard pc_map;
};
class AuctionManager : public singleton <AuctionManager>
{
private:
// auction<6F><6E> <20><><EFBFBD>ϵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>۵<EFBFBD>.
typedef boost::unordered_map<DWORD, CItemCache *> TItemCacheMap;
TItemCacheMap auction_item_cache_map;
// auction<6F><6E> <20><><EFBFBD>ϵ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>̺<EFBFBD><CCBA><EFBFBD> <20><><EFBFBD>Ե<EFBFBD><D4B5><EFBFBD> <20>ʴ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>͵<EFBFBD>
AuctionBoard Auction;
SaleBoard Sale;
WishBoard Wish;
MyBidBoard MyBid;
public:
AuctionManager();
~AuctionManager();
void Initialize ();
void LoadAuctionItem ();
void LoadAuctionInfo ();
void LoadSaleInfo ();
void LoadWishInfo ();
void LoadMyBidInfo ();
void Boot(CPeer* peer);
bool InsertItemCache (CItemCache *item_cache, bool bSkipQuery = false);
bool InsertItemCache (TPlayerItem * pNew, bool bSkipQuery = false);
bool DeleteItemCache (DWORD item_id);
CItemCache* GetItemCache (DWORD item_id);
size_t GetAuctionItemSize()
{
return auction_item_cache_map.size();
}
size_t GetAuctionSize()
{
return Auction.Size();
}
size_t GetSaleSize()
{
return Sale.Size();
}
size_t GetWishSize()
{
return Wish.Size();
}
size_t GetMyBidSize()
{
return MyBid.Size();
}
void InsertAuctionItemInfoCache (TAuctionItemInfo *pNew, bool bSkipQuery = false)
{
Auction.InsertItemInfo (pNew, bSkipQuery);
}
CAuctionItemInfoCache* GetAuctionItemInfoCache (DWORD item_id)
{
return Auction.GetItemInfoCache(item_id);
}
void InsertSaleItemInfoCache (TSaleItemInfo *pNew, bool bSkipQuery = false)
{
Sale.InsertItemInfo (pNew, bSkipQuery);
}
CSaleItemInfoCache* GetSaleItemInfoCache (DWORD item_id)
{
return Sale.GetItemInfoCache(item_id);
}
void InsertWishItemInfoCache (TWishItemInfo *pNew, bool bSkipQuery = false)
{
Wish.InsertItemInfo (pNew, bSkipQuery);
}
CWishItemInfoCache* GetWishItemInfoCache (DWORD item_id, DWORD wisher_id)
{
return Wish.GetItemInfoCache(WishBoard::Key (item_id, wisher_id));
}
void InsertMyBid (DWORD player_id, DWORD item_id, DWORD money)
{
MyBid.Insert (player_id, item_id, money);
}
AuctionResult EnrollInAuction(CItemCache* item_cache, TAuctionItemInfo &item_info);
AuctionResult EnrollInSale(CItemCache* item_cache, TSaleItemInfo &item_info);
AuctionResult EnrollInWish(TWishItemInfo &item_info);
AuctionResult Bid(DWORD bidder_id, const char* bidder_name, DWORD item_id, DWORD bid_price);
AuctionResult Impur(DWORD purchaser_id, const char* purchaser_name, DWORD item_id);
AuctionResult GetAuctionedItem (DWORD actor_id, DWORD item_id, TPlayerItem& item);
AuctionResult BuySoldItem (DWORD actor_id, DWORD item_id, TPlayerItem& item);
AuctionResult CancelAuction (DWORD actor_id, DWORD item_id, TPlayerItem& item);
AuctionResult CancelWish (DWORD actor_id, DWORD item_num);
AuctionResult CancelSale (DWORD actor_id, DWORD item_id, TPlayerItem& item);
AuctionResult DeleteAuctionItem (DWORD actor_id, DWORD item_id);
AuctionResult DeleteSaleItem (DWORD actor_id, DWORD item_id);
AuctionResult ReBid(DWORD bidder_id, const char* bidder_name, DWORD item_id, DWORD bid_price);
AuctionResult BidCancel (DWORD bidder_id, DWORD item_id);
};
#endif
#endif

214
db/src/BlockCountry.cpp Normal file
View File

@ -0,0 +1,214 @@
// vim:ts=4 sw=4
/*********************************************************************
* date : 2007.05.31
* file : BlockCountry.cpp
* author : mhh
* description :
*/
#include "stdafx.h"
#include "BlockCountry.h"
#include "DBManager.h"
#define DO_ALL_BLOCK_IP(iter) \
for ((iter) = m_block_ip.begin(); (iter) != m_block_ip.end(); ++(iter))
#define DO_ALL_BLOCK_EXCEPTION(iter) \
for ((iter) = m_block_exception.begin(); (iter) != m_block_exception.end(); ++(iter))
CBlockCountry::CBlockCountry()
{
}
CBlockCountry::~CBlockCountry()
{
BLOCK_IP *block_ip;
BLOCK_IP_VECTOR::iterator iter;
DO_ALL_BLOCK_IP(iter)
{
block_ip = *iter;
delete block_ip;
}
m_block_ip.clear();
}
bool CBlockCountry::Load()
{
// load blocked ip
{
char szQuery[256];
snprintf(szQuery, sizeof(szQuery), "SELECT IP_FROM, IP_TO, COUNTRY_NAME FROM iptocountry");
SQLMsg * pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_ACCOUNT);
if (pMsg->Get()->uiNumRows == 0)
{
sys_err(" DirectQuery failed(%s)", szQuery);
delete pMsg;
return false;
}
MYSQL_ROW row;
for (int n = 0; (row = mysql_fetch_row(pMsg->Get()->pSQLResult)) != NULL; ++n)
{
BLOCK_IP *block_ip = new BLOCK_IP;
block_ip->ip_from = strtoul(row[0], NULL, 10);
block_ip->ip_to = strtoul(row[1], NULL, 10);
strlcpy(block_ip->country, row[2], sizeof(block_ip->country));
m_block_ip.push_back(block_ip);
sys_log(0, "BLOCKED_IP : %u - %u", block_ip->ip_from, block_ip->ip_to);
}
delete pMsg;
}
// load block exception account
{
char szQuery[256];
snprintf(szQuery, sizeof(szQuery), "SELECT login FROM block_exception");
SQLMsg * pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_ACCOUNT);
if (pMsg->Get()->uiNumRows == 0)
{
sys_err(" DirectQuery failed(%s)", szQuery);
delete pMsg;
return true;
}
MYSQL_ROW row;
for (int n = 0; (row = mysql_fetch_row(pMsg->Get()->pSQLResult)) != NULL; ++n)
{
const char *login = row[0];
m_block_exception.push_back(strdup(login));
sys_log(0, "BLOCK_EXCEPTION = %s", login);
}
delete pMsg;
}
return true;
}
bool CBlockCountry::IsBlockedCountryIp(const char *user_ip)
{
BLOCK_IP* block_ip;
BLOCK_IP_VECTOR::iterator iter;
struct in_addr st_addr;
#ifndef __WIN32__
if (0 == inet_aton(user_ip, &st_addr))
#else
unsigned long in_address;
in_address = inet_addr(user_ip);
st_addr.s_addr = in_address;
if (INADDR_NONE == in_address)
#endif
return true; // <20><><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD>ó<EFBFBD><C3B3>
DO_ALL_BLOCK_IP(iter)
{
block_ip = *iter;
if (st_addr.s_addr >= block_ip->ip_from && st_addr.s_addr <= block_ip->ip_to)
return true;
}
return false;
}
void CBlockCountry::SendBlockedCountryIp(CPeer *peer)
{
sys_log(0, "SendBlockedCountryIp start");
BLOCK_IP *block_ip;
BLOCK_IP_VECTOR::iterator iter;
TPacketBlockCountryIp packet;
DO_ALL_BLOCK_IP(iter)
{
block_ip = *iter;
packet.ip_from = block_ip->ip_from;
packet.ip_to = block_ip->ip_to;
peer->EncodeHeader(HEADER_DG_BLOCK_COUNTRY_IP, 0, sizeof(TPacketBlockCountryIp));
peer->Encode(&packet, sizeof(packet));
}
sys_log(0, "[DONE] CBlockCountry::SendBlockedCountryIp() : count = %d",
m_block_ip.size());
sys_log(0, "SendBlockedCountryIp end");
} /* end of CBlockCountry::SendBlockedCountryIp() */
void CBlockCountry::SendBlockException(CPeer *peer)
{
BLOCK_EXCEPTION_VECTOR::iterator iter;
DO_ALL_BLOCK_EXCEPTION(iter)
{
const char *login = *iter;
this->SendBlockExceptionOne(peer, login, BLOCK_EXCEPTION_CMD_ADD);
}
} /* end of CBlockCountry::SendBlockException() */
void CBlockCountry::SendBlockExceptionOne(CPeer *peer, const char *login, BYTE cmd)
{
if (NULL == peer || NULL == login)
return;
if (BLOCK_EXCEPTION_CMD_ADD != cmd && BLOCK_EXCEPTION_CMD_DEL != cmd)
return;
TPacketBlockException packet;
packet.cmd = cmd;
strlcpy(packet.login, login, sizeof(packet.login));
peer->EncodeHeader(HEADER_DG_BLOCK_EXCEPTION, 0, sizeof(TPacketBlockException));
peer->Encode(&packet, sizeof(packet));
}
void CBlockCountry::AddBlockException(const char *login)
{
BLOCK_EXCEPTION_VECTOR::iterator iter;
DO_ALL_BLOCK_EXCEPTION(iter)
{
const char *saved_login = *iter;
if (!strcmp(saved_login, login))
return;
}
m_block_exception.push_back(strdup(login));
return;
}
void CBlockCountry::DelBlockException(const char *login)
{
BLOCK_EXCEPTION_VECTOR::iterator iter;
DO_ALL_BLOCK_EXCEPTION(iter)
{
const char *saved_login = *iter;
if (!strcmp(saved_login, login))
{
::free((void*)saved_login);
m_block_exception.erase(iter);
return;
}
}
return;
}

44
db/src/BlockCountry.h Normal file
View File

@ -0,0 +1,44 @@
// vim: ts=4 sw=4
// Date : 2007.05.31
// File : BlockCountry.h
// Author : mhh
// Description :
#ifndef __INC_METIN_II_BLOCKCOUNTRY_H__
#define __INC_METIN_II_BLOCKCOUNTRY_H__
#include "Peer.h"
#define MAX_COUNTRY_NAME_LENGTH 50
class CBlockCountry : public singleton<CBlockCountry>
{
private:
struct BLOCK_IP
{
DWORD ip_from;
DWORD ip_to;
char country[MAX_COUNTRY_NAME_LENGTH + 1];
};
typedef std::vector<BLOCK_IP*> BLOCK_IP_VECTOR;
BLOCK_IP_VECTOR m_block_ip;
typedef std::vector<const char*> BLOCK_EXCEPTION_VECTOR;
BLOCK_EXCEPTION_VECTOR m_block_exception;
public:
CBlockCountry();
~CBlockCountry();
public:
bool Load();
bool IsBlockedCountryIp(const char *user_ip);
void SendBlockedCountryIp(CPeer *peer);
void SendBlockException(CPeer *peer);
void SendBlockExceptionOne(CPeer *peer, const char *login, BYTE cmd);
void AddBlockException(const char *login);
void DelBlockException(const char *login);
};
#endif

365
db/src/Cache.cpp Normal file
View File

@ -0,0 +1,365 @@
#include "stdafx.h"
#include "Cache.h"
#include "QID.h"
#include "ClientManager.h"
#ifdef __AUCTION__
#include "AuctionManager.h"
#endif
#include "Main.h"
extern CPacketInfo g_item_info;
extern int g_iPlayerCacheFlushSeconds;
extern int g_iItemCacheFlushSeconds;
extern int g_test_server;
// MYSHOP_PRICE_LIST
extern int g_iItemPriceListTableCacheFlushSeconds;
// END_OF_MYSHOP_PRICE_LIST
//
extern int g_item_count;
const int auctionMinFlushSec = 1800;
CItemCache::CItemCache()
{
m_expireTime = MIN(1800, g_iItemCacheFlushSeconds);
}
CItemCache::~CItemCache()
{
}
// <20>̰<EFBFBD> <20>̻<EFBFBD><CCBB>ѵ<EFBFBD>...
// Delete<74><65> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, Cache<68><65> <20><><EFBFBD><EFBFBD><EFBFBD>ؾ<EFBFBD> <20>ϴ°<CFB4> <20>ƴѰ<C6B4>???
// <20>ٵ<EFBFBD> Cache<68><65> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>κ<EFBFBD><CEBA><EFBFBD> <20><><EFBFBD><EFBFBD>.
// <20><> ã<><C3A3> <20>ǰ<EFBFBD>?
// <20>̷<EFBFBD><CCB7><EFBFBD> <20>س<EFBFBD><D8B3><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>...
// <20>̹<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ε<EFBFBD>... Ȯ<>λ<EFBFBD><CEBB><EFBFBD>??????
// fixme
// by rtsummit
void CItemCache::Delete()
{
if (m_data.vnum == 0)
return;
//char szQuery[QUERY_MAX_LEN];
//szQuery[QUERY_MAX_LEN] = '\0';
if (g_test_server)
sys_log(0, "ItemCache::Delete : DELETE %u", m_data.id);
m_data.vnum = 0;
m_bNeedQuery = true;
m_lastUpdateTime = time(0);
OnFlush();
//m_bNeedQuery = false;
//m_lastUpdateTime = time(0) - m_expireTime; // <20>ٷ<EFBFBD> Ÿ<>Ӿƿ<D3BE> <20>ǵ<EFBFBD><C7B5><EFBFBD> <20><><EFBFBD><EFBFBD>.
}
void CItemCache::OnFlush()
{
if (m_data.vnum == 0) // vnum<75><6D> 0<≯<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD><CFB6><EFBFBD> ǥ<>õ<EFBFBD> <20><><EFBFBD>̴<EFBFBD>.
{
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery), "DELETE FROM item%s WHERE id=%u", GetTablePostfix(), m_data.id);
CDBManager::instance().ReturnQuery(szQuery, QID_ITEM_DESTROY, 0, NULL);
if (g_test_server)
sys_log(0, "ItemCache::Flush : DELETE %u %s", m_data.id, szQuery);
}
else
{
long alSockets[ITEM_SOCKET_MAX_NUM];
TPlayerItemAttribute aAttr[ITEM_ATTRIBUTE_MAX_NUM];
bool isSocket = false, isAttr = false;
memset(&alSockets, 0, sizeof(long) * ITEM_SOCKET_MAX_NUM);
memset(&aAttr, 0, sizeof(TPlayerItemAttribute) * ITEM_ATTRIBUTE_MAX_NUM);
TPlayerItem * p = &m_data;
if (memcmp(alSockets, p->alSockets, sizeof(long) * ITEM_SOCKET_MAX_NUM))
isSocket = true;
if (memcmp(aAttr, p->aAttr, sizeof(TPlayerItemAttribute) * ITEM_ATTRIBUTE_MAX_NUM))
isAttr = true;
char szColumns[QUERY_MAX_LEN];
char szValues[QUERY_MAX_LEN];
char szUpdate[QUERY_MAX_LEN];
int iLen = snprintf(szColumns, sizeof(szColumns), "id, owner_id, window, pos, count, vnum");
int iValueLen = snprintf(szValues, sizeof(szValues), "%u, %u, %d, %d, %u, %u",
p->id, p->owner, p->window, p->pos, p->count, p->vnum);
int iUpdateLen = snprintf(szUpdate, sizeof(szUpdate), "owner_id=%u, window=%d, pos=%d, count=%u, vnum=%u",
p->owner, p->window, p->pos, p->count, p->vnum);
if (isSocket)
{
iLen += snprintf(szColumns + iLen, sizeof(szColumns) - iLen, ", socket0, socket1, socket2");
iValueLen += snprintf(szValues + iValueLen, sizeof(szValues) - iValueLen,
", %lu, %lu, %lu", p->alSockets[0], p->alSockets[1], p->alSockets[2]);
iUpdateLen += snprintf(szUpdate + iUpdateLen, sizeof(szUpdate) - iUpdateLen,
", socket0=%lu, socket1=%lu, socket2=%lu", p->alSockets[0], p->alSockets[1], p->alSockets[2]);
}
if (isAttr)
{
iLen += snprintf(szColumns + iLen, sizeof(szColumns) - iLen,
", attrtype0, attrvalue0, attrtype1, attrvalue1, attrtype2, attrvalue2, attrtype3, attrvalue3"
", attrtype4, attrvalue4, attrtype5, attrvalue5, attrtype6, attrvalue6");
iValueLen += snprintf(szValues + iValueLen, sizeof(szValues) - iValueLen,
", %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",
p->aAttr[0].bType, p->aAttr[0].sValue,
p->aAttr[1].bType, p->aAttr[1].sValue,
p->aAttr[2].bType, p->aAttr[2].sValue,
p->aAttr[3].bType, p->aAttr[3].sValue,
p->aAttr[4].bType, p->aAttr[4].sValue,
p->aAttr[5].bType, p->aAttr[5].sValue,
p->aAttr[6].bType, p->aAttr[6].sValue);
iUpdateLen += snprintf(szUpdate + iUpdateLen, sizeof(szUpdate) - iUpdateLen,
", attrtype0=%d, attrvalue0=%d"
", attrtype1=%d, attrvalue1=%d"
", attrtype2=%d, attrvalue2=%d"
", attrtype3=%d, attrvalue3=%d"
", attrtype4=%d, attrvalue4=%d"
", attrtype5=%d, attrvalue5=%d"
", attrtype6=%d, attrvalue6=%d",
p->aAttr[0].bType, p->aAttr[0].sValue,
p->aAttr[1].bType, p->aAttr[1].sValue,
p->aAttr[2].bType, p->aAttr[2].sValue,
p->aAttr[3].bType, p->aAttr[3].sValue,
p->aAttr[4].bType, p->aAttr[4].sValue,
p->aAttr[5].bType, p->aAttr[5].sValue,
p->aAttr[6].bType, p->aAttr[6].sValue);
}
char szItemQuery[QUERY_MAX_LEN + QUERY_MAX_LEN];
snprintf(szItemQuery, sizeof(szItemQuery), "REPLACE INTO item%s (%s) VALUES(%s)", GetTablePostfix(), szColumns, szValues);
if (g_test_server)
sys_log(0, "ItemCache::Flush :REPLACE (%s)", szItemQuery);
CDBManager::instance().ReturnQuery(szItemQuery, QID_ITEM_SAVE, 0, NULL);
//g_item_info.Add(p->vnum);
++g_item_count;
}
m_bNeedQuery = false;
}
//
// CPlayerTableCache
//
CPlayerTableCache::CPlayerTableCache()
{
m_expireTime = MIN(1800, g_iPlayerCacheFlushSeconds);
}
CPlayerTableCache::~CPlayerTableCache()
{
}
void CPlayerTableCache::OnFlush()
{
if (g_test_server)
sys_log(0, "PlayerTableCache::Flush : %s", m_data.name);
char szQuery[QUERY_MAX_LEN];
CreatePlayerSaveQuery(szQuery, sizeof(szQuery), &m_data);
CDBManager::instance().ReturnQuery(szQuery, QID_PLAYER_SAVE, 0, NULL);
}
// MYSHOP_PRICE_LIST
//
// CItemPriceListTableCache class implementation
//
const int CItemPriceListTableCache::s_nMinFlushSec = 1800;
CItemPriceListTableCache::CItemPriceListTableCache()
{
m_expireTime = MIN(s_nMinFlushSec, g_iItemPriceListTableCacheFlushSeconds);
}
void CItemPriceListTableCache::UpdateList(const TItemPriceListTable* pUpdateList)
{
//
// <20>̹<EFBFBD> ij<>̵<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>۰<EFBFBD> <20>ߺ<EFBFBD><DFBA><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ã<><C3A3> <20>ߺ<EFBFBD><DFBA><EFBFBD><EFBFBD><EFBFBD> <20>ʴ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> tmpvec <20><> <20>ִ´<D6B4>.
//
std::vector<TItemPriceInfo> tmpvec;
for (uint idx = 0; idx < m_data.byCount; ++idx)
{
const TItemPriceInfo* pos = pUpdateList->aPriceInfo;
for (; pos != pUpdateList->aPriceInfo + pUpdateList->byCount && m_data.aPriceInfo[idx].dwVnum != pos->dwVnum; ++pos)
;
if (pos == pUpdateList->aPriceInfo + pUpdateList->byCount)
tmpvec.push_back(m_data.aPriceInfo[idx]);
}
//
// pUpdateList <20><> m_data <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> tmpvec <20><> <20>տ<EFBFBD><D5BF><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ŭ <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
//
if (pUpdateList->byCount > SHOP_PRICELIST_MAX_NUM)
{
sys_err("Count overflow!");
return;
}
m_data.byCount = pUpdateList->byCount;
thecore_memcpy(m_data.aPriceInfo, pUpdateList->aPriceInfo, sizeof(TItemPriceInfo) * pUpdateList->byCount);
int nDeletedNum; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if (pUpdateList->byCount < SHOP_PRICELIST_MAX_NUM)
{
size_t sizeAddOldDataSize = SHOP_PRICELIST_MAX_NUM - pUpdateList->byCount;
if (tmpvec.size() < sizeAddOldDataSize)
sizeAddOldDataSize = tmpvec.size();
thecore_memcpy(m_data.aPriceInfo + pUpdateList->byCount, &tmpvec[0], sizeof(TItemPriceInfo) * sizeAddOldDataSize);
m_data.byCount += sizeAddOldDataSize;
nDeletedNum = tmpvec.size() - sizeAddOldDataSize;
}
else
nDeletedNum = tmpvec.size();
m_bNeedQuery = true;
sys_log(0,
"ItemPriceListTableCache::UpdateList : OwnerID[%u] Update [%u] Items, Delete [%u] Items, Total [%u] Items",
m_data.dwOwnerID, pUpdateList->byCount, nDeletedNum, m_data.byCount);
}
void CItemPriceListTableCache::OnFlush()
{
char szQuery[QUERY_MAX_LEN];
//
// <20><> ij<><C4B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ڿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DB <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
//
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);
//
// ij<><C4B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> DB <20><> <20><><EFBFBD><EFBFBD>.
//
for (int idx = 0; idx < m_data.byCount; ++idx)
{
snprintf(szQuery, sizeof(szQuery),
"INSERT INTO myshop_pricelist%s(owner_id, item_vnum, price) VALUES(%u, %u, %u)",
GetTablePostfix(), m_data.dwOwnerID, m_data.aPriceInfo[idx].dwVnum, m_data.aPriceInfo[idx].dwPrice);
CDBManager::instance().ReturnQuery(szQuery, QID_ITEMPRICE_SAVE, 0, NULL);
}
sys_log(0, "ItemPriceListTableCache::Flush : OwnerID[%u] Update [%u]Items", m_data.dwOwnerID, m_data.byCount);
m_bNeedQuery = false;
}
// END_OF_MYSHOP_PRICE_LIST
#ifdef __AUCTION__
CAuctionItemInfoCache::CAuctionItemInfoCache()
{
m_expireTime = MIN (auctionMinFlushSec, g_iItemCacheFlushSeconds);
}
CAuctionItemInfoCache::~CAuctionItemInfoCache()
{
}
void CAuctionItemInfoCache::Delete()
{
if (m_data.item_num == 0)
return;
if (g_test_server)
sys_log(0, "CAuctionItemInfoCache::Delete : DELETE %u", m_data.item_id);
m_data.item_num = 0;
m_bNeedQuery = true;
m_lastUpdateTime = time(0);
OnFlush();
delete this;
}
void CAuctionItemInfoCache::OnFlush()
{
char szQuery[QUERY_MAX_LEN];
if (m_data.item_num == 0)
{
snprintf(szQuery, sizeof(szQuery), "DELETE FROM auction where item_id = %d", m_data.item_id);
CDBManager::instance().AsyncQuery(szQuery);
}
else
{
snprintf(szQuery, sizeof(szQuery), "REPLACE INTO auction VALUES (%u, %d, %d, %u, \"%s\", %u, %u, %u, %u)",
m_data.item_num, m_data.offer_price, m_data.price, m_data.offer_id, m_data.shown_name, (DWORD)m_data.empire, (DWORD)m_data.expired_time,
m_data.item_id, m_data.bidder_id);
CDBManager::instance().AsyncQuery(szQuery);
}
}
CSaleItemInfoCache::CSaleItemInfoCache()
{
m_expireTime = MIN (auctionMinFlushSec, g_iItemCacheFlushSeconds);
}
CSaleItemInfoCache::~CSaleItemInfoCache()
{
}
void CSaleItemInfoCache::Delete()
{
}
void CSaleItemInfoCache::OnFlush()
{
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery), "REPLACE INTO sale VALUES (%u, %d, %d, %u, \"%s\", %u, %u, %u, %u)",
m_data.item_num, m_data.offer_price, m_data.price, m_data.offer_id, m_data.shown_name, (DWORD)m_data.empire, (DWORD)m_data.expired_time,
m_data.item_id, m_data.wisher_id);
CDBManager::instance().AsyncQuery(szQuery);
}
CWishItemInfoCache::CWishItemInfoCache()
{
m_expireTime = MIN (auctionMinFlushSec, g_iItemCacheFlushSeconds);
}
CWishItemInfoCache::~CWishItemInfoCache()
{
}
void CWishItemInfoCache::Delete()
{
}
void CWishItemInfoCache::OnFlush()
{
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery), "REPLACE INTO wish VALUES (%u, %d, %d, %u, \"%s\", %u, %d)",
m_data.item_num, m_data.offer_price, m_data.price, m_data.offer_id, m_data.shown_name, (DWORD)m_data.empire, (DWORD)m_data.expired_time);
CDBManager::instance().AsyncQuery(szQuery);
}
#endif

97
db/src/Cache.h Normal file
View File

@ -0,0 +1,97 @@
// vim:ts=8 sw=4
#ifndef __INC_DB_CACHE_H__
#define __INC_DB_CACHE_H__
#include "../../common/cache.h"
#include "../../common/auction_table.h"
class CItemCache : public cache<TPlayerItem>
{
public:
CItemCache();
virtual ~CItemCache();
void Delete();
virtual void OnFlush();
};
class CPlayerTableCache : public cache<TPlayerTable>
{
public:
CPlayerTableCache();
virtual ~CPlayerTableCache();
virtual void OnFlush();
DWORD GetLastUpdateTime() { return m_lastUpdateTime; }
};
// MYSHOP_PRICE_LIST
/**
* @class CItemPriceListTableCache
* @brief <09><><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> ij<><C4B3> class
* @version 05/06/10 Bang2ni - First release.
*/
class CItemPriceListTableCache : public cache< TItemPriceListTable >
{
public:
/// Constructor
/**
* ij<><C4B3> <20><><EFBFBD><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
*/
CItemPriceListTableCache(void);
/// <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>
/**
* @param [in] pUpdateList <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ
*
* ij<>õ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> á<><C3A1> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ij<>̵<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ڿ<EFBFBD><DABF><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
*/
void UpdateList(const TItemPriceListTable* pUpdateList);
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DB <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
virtual void OnFlush(void);
private:
static const int s_nMinFlushSec; ///< Minimum cache expire time
};
// END_OF_MYSHOP_PRICE_LIST
#ifdef __AUCTION__
class CAuctionItemInfoCache : public cache <TAuctionItemInfo>
{
public:
typedef TWishItemInfo value_type;
CAuctionItemInfoCache();
virtual ~CAuctionItemInfoCache();
void Delete();
virtual void OnFlush();
};
class CSaleItemInfoCache : public cache <TSaleItemInfo>
{
public:
typedef TWishItemInfo value_type;
CSaleItemInfoCache();
virtual ~CSaleItemInfoCache();
void Delete();
virtual void OnFlush();
};
class CWishItemInfoCache : public cache <TWishItemInfo>
{
public:
typedef TWishItemInfo value_type;
CWishItemInfoCache();
virtual ~CWishItemInfoCache();
void Delete();
virtual void OnFlush();
};
#endif
#endif

4984
db/src/ClientManager.cpp Normal file

File diff suppressed because it is too large Load Diff

578
db/src/ClientManager.h Normal file
View File

@ -0,0 +1,578 @@
// 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
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ <20><>û <20><><EFBFBD><EFBFBD>
/**
* first: Peer handle
* second: <20><>û<EFBFBD><C3BB> <20>÷<EFBFBD><C3B7>̾<EFBFBD><CCBE><EFBFBD> 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;
};
//<2F><><EFBFBD>ϼ<EFBFBD><CFBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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(); // <20><><EFBFBD>ӵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
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
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ ij<>ø<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>.
/**
* @param [in] dwID <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.(<28>÷<EFBFBD><C3B7>̾<EFBFBD> ID)
* @return <09><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ ij<><C4B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
CItemPriceListTableCache* GetItemPriceListCache(DWORD dwID);
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ ij<>ø<EFBFBD> <20>ִ´<D6B4>.
/**
* @param [in] pItemPriceList ij<>ÿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ
*
* ij<>ð<EFBFBD> <20>̹<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Update <20><> <20>ƴ<EFBFBD> replace <20>Ѵ<EFBFBD>.
*/
void PutItemPriceListCache(const TItemPriceListTable* pItemPriceList);
/// Flush <20>ð<EFBFBD><C3B0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ ij<>ø<EFBFBD> Flush <20><><EFBFBD>ְ<EFBFBD> ij<>ÿ<EFBFBD><C3BF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
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); //<2F><><EFBFBD>ϼ<EFBFBD><CFBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɿ<EFBFBD><C9BF><EFBFBD> <20><><EFBFBD>ɾ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>Լ<EFBFBD>
void ItemAward(CPeer * peer, char* login); //<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
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<78><74><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> mob_proto, item_proto<74><6F> real db<64><62> <20>ݿ<EFBFBD>.
// item_proto, mob_proto<74><6F> db<64><62> <20>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD><EFBFBD> <20>ʾƵ<CABE>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ư<EFBFBD><C6B0>µ<EFBFBD><C2B5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,
// <09><EFBFBD><EEBFB5> <20><EFBFBD><EEBFA1> db<64><62> item_proto, mob_proto<74><6F> <20>о<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߻<EFBFBD><DFBB>Ѵ<EFBFBD>.
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
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Result ó<><C3B3>
/**
* @param peer <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>û<EFBFBD><C3BB> Game server <20><> peer <20><>ü <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param pMsg <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Result <20><> <20><><EFBFBD><EFBFBD> <20><>ü<EFBFBD><C3BC> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* <20>ε<EFBFBD><CEB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> ij<>ÿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> peer <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
*/
void RESULT_PRICELIST_LOAD(CPeer* peer, SQLMsg* pMsg);
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Result ó<><C3B3>
/**
* @param pMsg <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Result <20><> <20><><EFBFBD><EFBFBD> <20><>ü<EFBFBD><C3BC> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* <20>ε<EFBFBD><CEB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ ij<>ø<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20>Ѵ<EFBFBD>.
*/
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);
// <20><>ȥ
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
// <20><><EFBFBD>λ<EFBFBD><CEBB><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ <20><>Ŷ(HEADER_GD_MYSHOP_PRICELIST_UPDATE) ó<><C3B3><EFBFBD>Լ<EFBFBD>
/**
* @param [in] pPacket <20><>Ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
void MyshopPricelistUpdate(const TPacketMyshopPricelistHeader* pPacket);
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ <20><>û <20><>Ŷ(HEADER_GD_MYSHOP_PRICELIST_REQ) ó<><C3B3><EFBFBD>Լ<EFBFBD>
/**
* @param peer <20><>Ŷ<EFBFBD><C5B6> <20><><EFBFBD><EFBFBD> Game server <20><> peer <20><>ü<EFBFBD><C3BC> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param [in] dwHandle <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>û<EFBFBD><C3BB> peer <20><> <20>ڵ<EFBFBD>
* @param [in] dwPlayerID <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><>û<EFBFBD><C3BB> <20>÷<EFBFBD><C3B7>̾<EFBFBD><CCBE><EFBFBD> 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; // <20><><EFBFBD><EFBFBD> <20>޴<EFBFBD> <20><><EFBFBD><EFBFBD>
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 (<28><><EFBFBD><EFBFBD> <20>α<EFBFBD><CEB1><EFBFBD> <20>Ǿ<EFBFBD><C7BE>ִ<EFBFBD> <20><><EFBFBD><EFBFBD>)
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; // <20>÷<EFBFBD><C3B7>̾<EFBFBD> id<69><64> key
TItemCacheMap m_map_itemCache; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> id<69><64> key
TItemCacheSetPtrMap m_map_pkItemCacheSetPtr; // <20>÷<EFBFBD><C3B7>̾<EFBFBD> id<69><64> key, <20><> <20>÷<EFBFBD><C3B7>̾ <20><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ij<><C4B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ֳ<EFBFBD>?
// MYSHOP_PRICE_LIST
/// <20>÷<EFBFBD><C3B7>̾ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ map. key: <20>÷<EFBFBD><C3B7>̾<EFBFBD> ID, value: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ ij<><C4B3>
TItemPriceListCacheMap m_mapItemPriceListCache; ///< <20>÷<EFBFBD><C3B7>̾ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ
// 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:
/* <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʱ<EFBFBD>ȭ
**/
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

1524
db/src/ClientManagerBoot.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,77 @@
// vim:ts=4 sw=4
#include "stdafx.h"
#include "ClientManager.h"
#include "Main.h"
#include "Config.h"
#include "DBManager.h"
#include "QID.h"
void CClientManager::LoadEventFlag()
{
char szQuery[1024];
snprintf(szQuery, sizeof(szQuery), "SELECT szName, lValue FROM quest%s WHERE dwPID = 0", GetTablePostfix());
std::auto_ptr<SQLMsg> pmsg(CDBManager::instance().DirectQuery(szQuery));
SQLResult* pRes = pmsg->Get();
if (pRes->uiNumRows)
{
MYSQL_ROW row;
while ((row = mysql_fetch_row(pRes->pSQLResult)))
{
TPacketSetEventFlag p;
strlcpy(p.szFlagName, row[0], sizeof(p.szFlagName));
str_to_number(p.lValue, row[1]);
sys_log(0, "EventFlag Load %s %d", p.szFlagName, p.lValue);
m_map_lEventFlag.insert(std::make_pair(std::string(p.szFlagName), p.lValue));
ForwardPacket(HEADER_DG_SET_EVENT_FLAG, &p, sizeof(TPacketSetEventFlag));
}
}
}
void CClientManager::SetEventFlag(TPacketSetEventFlag* p)
{
ForwardPacket(HEADER_DG_SET_EVENT_FLAG, p, sizeof(TPacketSetEventFlag));
bool bChanged = false;
typeof(m_map_lEventFlag.begin()) it = m_map_lEventFlag.find(p->szFlagName);
if (it == m_map_lEventFlag.end())
{
bChanged = true;
m_map_lEventFlag.insert(std::make_pair(std::string(p->szFlagName), p->lValue));
}
else if (it->second != p->lValue)
{
bChanged = true;
it->second = p->lValue;
}
if (bChanged)
{
char szQuery[1024];
snprintf(szQuery, sizeof(szQuery),
"REPLACE INTO quest%s (dwPID, szName, szState, lValue) VALUES(0, '%s', '', %ld)",
GetTablePostfix(), p->szFlagName, p->lValue);
szQuery[1023] = '\0';
//CDBManager::instance().ReturnQuery(szQuery, QID_QUEST_SAVE, 0, NULL);
CDBManager::instance().AsyncQuery(szQuery);
sys_log(0, "HEADER_GD_SET_EVENT_FLAG : Changed CClientmanager::SetEventFlag(%s %d) ", p->szFlagName, p->lValue);
return;
}
sys_log(0, "HEADER_GD_SET_EVENT_FLAG : No Changed CClientmanager::SetEventFlag(%s %d) ", p->szFlagName, p->lValue);
}
void CClientManager::SendEventFlagsOnSetup(CPeer* peer)
{
typeof(m_map_lEventFlag.begin()) it;
for (it = m_map_lEventFlag.begin(); it != m_map_lEventFlag.end(); ++it)
{
TPacketSetEventFlag p;
strlcpy(p.szFlagName, it->first.c_str(), sizeof(p.szFlagName));
p.lValue = it->second;
peer->EncodeHeader(HEADER_DG_SET_EVENT_FLAG, 0, sizeof(TPacketSetEventFlag));
peer->Encode(&p, sizeof(TPacketSetEventFlag));
}
}

View File

@ -0,0 +1,244 @@
// vim:ts=4 sw=4
#include "stdafx.h"
#include "ClientManager.h"
#include "Main.h"
#include "Config.h"
#include "DBManager.h"
#include "QID.h"
#include "GuildManager.h"
void CClientManager::GuildCreate(CPeer * peer, DWORD dwGuildID)
{
sys_log(0, "GuildCreate %u", dwGuildID);
ForwardPacket(HEADER_DG_GUILD_LOAD, &dwGuildID, sizeof(DWORD));
CGuildManager::instance().Load(dwGuildID);
}
void CClientManager::GuildChangeGrade(CPeer* peer, TPacketGuild* p)
{
sys_log(0, "GuildChangeGrade %u %u", p->dwGuild, p->dwInfo);
ForwardPacket(HEADER_DG_GUILD_CHANGE_GRADE, p, sizeof(TPacketGuild));
}
void CClientManager::GuildAddMember(CPeer* peer, TPacketGDGuildAddMember * p)
{
CGuildManager::instance().TouchGuild(p->dwGuild);
sys_log(0, "GuildAddMember %u %u", p->dwGuild, p->dwPID);
char szQuery[512];
snprintf(szQuery, sizeof(szQuery),
"INSERT INTO guild_member%s VALUES(%u, %u, %d, 0, 0)",
GetTablePostfix(), p->dwPID, p->dwGuild, p->bGrade);
std::auto_ptr<SQLMsg> pmsg_insert(CDBManager::instance().DirectQuery(szQuery));
snprintf(szQuery, sizeof(szQuery),
"SELECT pid, grade, is_general, offer, level, job, name FROM guild_member%s, player%s WHERE guild_id = %u and pid = id and pid = %u", GetTablePostfix(), GetTablePostfix(), p->dwGuild, p->dwPID);
std::auto_ptr<SQLMsg> pmsg(CDBManager::instance().DirectQuery(szQuery));
if (pmsg->Get()->uiNumRows == 0)
{
sys_err("Query failed when getting guild member data %s", pmsg->stQuery.c_str());
return;
}
MYSQL_ROW row = mysql_fetch_row(pmsg->Get()->pSQLResult);
if (!row[0] || !row[1])
return;
TPacketDGGuildMember dg;
dg.dwGuild = p->dwGuild;
str_to_number(dg.dwPID, row[0]);
str_to_number(dg.bGrade, row[1]);
str_to_number(dg.isGeneral, row[2]);
str_to_number(dg.dwOffer, row[3]);
str_to_number(dg.bLevel, row[4]);
str_to_number(dg.bJob, row[5]);
strlcpy(dg.szName, row[6], sizeof(dg.szName));
ForwardPacket(HEADER_DG_GUILD_ADD_MEMBER, &dg, sizeof(TPacketDGGuildMember));
}
void CClientManager::GuildRemoveMember(CPeer* peer, TPacketGuild* p)
{
sys_log(0, "GuildRemoveMember %u %u", p->dwGuild, p->dwInfo);
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild_member%s WHERE pid=%u and guild_id=%u", GetTablePostfix(), p->dwInfo, p->dwGuild);
CDBManager::instance().AsyncQuery(szQuery);
snprintf(szQuery, sizeof(szQuery), "REPLACE INTO quest%s (dwPID, szName, szState, lValue) VALUES(%u, 'guild_manage', 'withdraw_time', %u)", GetTablePostfix(), p->dwInfo, (DWORD) GetCurrentTime());
CDBManager::instance().AsyncQuery(szQuery);
ForwardPacket(HEADER_DG_GUILD_REMOVE_MEMBER, p, sizeof(TPacketGuild));
}
void CClientManager::GuildSkillUpdate(CPeer* peer, TPacketGuildSkillUpdate* p)
{
sys_log(0, "GuildSkillUpdate %d", p->amount);
ForwardPacket(HEADER_DG_GUILD_SKILL_UPDATE, p, sizeof(TPacketGuildSkillUpdate));
}
void CClientManager::GuildExpUpdate(CPeer* peer, TPacketGuildExpUpdate* p)
{
sys_log(0, "GuildExpUpdate %d", p->amount);
ForwardPacket(HEADER_DG_GUILD_EXP_UPDATE, p, sizeof(TPacketGuildExpUpdate), 0, peer);
}
void CClientManager::GuildChangeMemberData(CPeer* peer, TPacketGuildChangeMemberData* p)
{
sys_log(0, "GuildChangeMemberData %u %u %d %d", p->pid, p->offer, p->level, p->grade);
ForwardPacket(HEADER_DG_GUILD_CHANGE_MEMBER_DATA, p, sizeof(TPacketGuildChangeMemberData), 0, peer);
}
void CClientManager::GuildDisband(CPeer* peer, TPacketGuild* p)
{
sys_log(0, "GuildDisband %u", p->dwGuild);
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild%s WHERE id=%u", GetTablePostfix(), p->dwGuild);
CDBManager::instance().AsyncQuery(szQuery);
snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild_grade%s WHERE guild_id=%u", GetTablePostfix(), p->dwGuild);
CDBManager::instance().AsyncQuery(szQuery);
snprintf(szQuery, sizeof(szQuery), "REPLACE INTO quest%s (dwPID, szName, szState, lValue) SELECT pid, 'guild_manage', 'withdraw_time', %u FROM guild_member%s WHERE guild_id = %u", GetTablePostfix(), (DWORD) GetCurrentTime(), GetTablePostfix(), p->dwGuild);
CDBManager::instance().AsyncQuery(szQuery);
snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild_member%s WHERE guild_id=%u", GetTablePostfix(), p->dwGuild);
CDBManager::instance().AsyncQuery(szQuery);
snprintf(szQuery, sizeof(szQuery), "DELETE FROM guild_comment%s WHERE guild_id=%u", GetTablePostfix(), p->dwGuild);
CDBManager::instance().AsyncQuery(szQuery);
ForwardPacket(HEADER_DG_GUILD_DISBAND, p, sizeof(TPacketGuild));
}
const char* __GetWarType(int n)
{
switch (n)
{
case 0 :
return "<EFBFBD>п<EFBFBD>";
case 1 :
return "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>";
case 2 :
return "<EFBFBD><EFBFBD>ȣ";
default :
return "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȣ";
}
}
void CClientManager::GuildWar(CPeer* peer, TPacketGuildWar* p)
{
switch (p->bWar)
{
case GUILD_WAR_SEND_DECLARE:
sys_log(0, "GuildWar: GUILD_WAR_SEND_DECLARE type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().AddDeclare(p->bType, p->dwGuildFrom, p->dwGuildTo);
break;
case GUILD_WAR_REFUSE:
sys_log(0, "GuildWar: GUILD_WAR_REFUSE type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
break;
/*
case GUILD_WAR_WAIT_START:
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
if (!CGuildManager::instance().WaitStart(p))
p->bWar = GUILD_WAR_CANCEL;
break;
*/
case GUILD_WAR_WAIT_START:
sys_log(0, "GuildWar: GUILD_WAR_WAIT_START type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
case GUILD_WAR_RESERVE: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
if (p->bWar != GUILD_WAR_WAIT_START)
sys_log(0, "GuildWar: GUILD_WAR_RESERVE type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().RemoveDeclare(p->dwGuildFrom, p->dwGuildTo);
if (!CGuildManager::instance().ReserveWar(p))
p->bWar = GUILD_WAR_CANCEL;
else
p->bWar = GUILD_WAR_RESERVE;
break;
case GUILD_WAR_ON_WAR: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>Ų<EFBFBD><C5B2>. (<28>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD> <20>ٷ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><>)
sys_log(0, "GuildWar: GUILD_WAR_ON_WAR type(%s) guild(%d - %d)", __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: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
sys_log(0, "GuildWar: GUILD_WAR_OVER type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().RecvWarOver(p->dwGuildFrom, p->dwGuildTo, p->bType, p->lWarPrice);
break;
case GUILD_WAR_END: // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
sys_log(0, "GuildWar: GUILD_WAR_END type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().RecvWarEnd(p->dwGuildFrom, p->dwGuildTo);
return; // NOTE: RecvWarEnd<6E><64><EFBFBD><EFBFBD> <20><>Ŷ<EFBFBD><C5B6> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ε<EFBFBD>ij<EFBFBD><C4B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
case GUILD_WAR_CANCEL :
sys_log(0, "GuildWar: GUILD_WAR_CANCEL type(%s) guild(%d - %d)", __GetWarType(p->bType), p->dwGuildFrom, p->dwGuildTo);
CGuildManager::instance().CancelWar(p->dwGuildFrom, p->dwGuildTo);
break;
}
ForwardPacket(HEADER_DG_GUILD_WAR, p, sizeof(TPacketGuildWar));
}
void CClientManager::GuildWarScore(CPeer* peer, TPacketGuildWarScore * p)
{
CGuildManager::instance().UpdateScore(p->dwGuildGainPoint, p->dwGuildOpponent, p->lScore, p->lBetScore);
}
void CClientManager::GuildChangeLadderPoint(TPacketGuildLadderPoint* p)
{
sys_log(0, "GuildChangeLadderPoint Recv %u %d", p->dwGuild, p->lChange);
CGuildManager::instance().ChangeLadderPoint(p->dwGuild, p->lChange);
}
void CClientManager::GuildUseSkill(TPacketGuildUseSkill* p)
{
sys_log(0, "GuildUseSkill Recv %u %d", p->dwGuild, p->dwSkillVnum);
CGuildManager::instance().UseSkill(p->dwGuild, p->dwSkillVnum, p->dwCooltime);
SendGuildSkillUsable(p->dwGuild, p->dwSkillVnum, false);
}
void CClientManager::SendGuildSkillUsable(DWORD guild_id, DWORD dwSkillVnum, bool bUsable)
{
sys_log(0, "SendGuildSkillUsable Send %u %d %s", guild_id, dwSkillVnum, bUsable?"true":"false");
TPacketGuildSkillUsableChange p;
p.dwGuild = guild_id;
p.dwSkillVnum = dwSkillVnum;
p.bUsable = bUsable;
ForwardPacket(HEADER_DG_GUILD_SKILL_USABLE_CHANGE, &p, sizeof(TPacketGuildSkillUsableChange));
}
void CClientManager::GuildChangeMaster(TPacketChangeGuildMaster* p)
{
if (CGuildManager::instance().ChangeMaster(p->dwGuildID, p->idFrom, p->idTo) == true)
{
TPacketChangeGuildMaster packet;
packet.dwGuildID = p->dwGuildID;
packet.idFrom = 0;
packet.idTo = 0;
ForwardPacket(HEADER_DG_ACK_CHANGE_GUILD_MASTER, &packet, sizeof(packet));
}
}

View File

@ -0,0 +1,40 @@
// vim:ts=4 sw=4
#include "stdafx.h"
#include "ClientManager.h"
void CClientManager::UpdateHorseName(TPacketUpdateHorseName* data, CPeer* peer)
{
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "REPLACE INTO horse_name VALUES(%u, '%s')", data->dwPlayerID, data->szHorseName);
std::auto_ptr<SQLMsg> pmsg_insert(CDBManager::instance().DirectQuery(szQuery));
ForwardPacket(HEADER_DG_UPDATE_HORSE_NAME, data, sizeof(TPacketUpdateHorseName), 0, peer);
}
void CClientManager::AckHorseName(DWORD dwPID, CPeer* peer)
{
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "SELECT name FROM horse_name WHERE id = %u", dwPID);
std::auto_ptr<SQLMsg> pmsg(CDBManager::instance().DirectQuery(szQuery));
TPacketUpdateHorseName packet;
packet.dwPlayerID = dwPID;
if (pmsg->Get()->uiNumRows == 0)
{
memset(packet.szHorseName, 0, sizeof (packet.szHorseName));
}
else
{
MYSQL_ROW row = mysql_fetch_row(pmsg->Get()->pSQLResult);
strlcpy(packet.szHorseName, row[0], sizeof(packet.szHorseName));
}
peer->EncodeHeader(HEADER_DG_ACK_HORSE_NAME, 0, sizeof(TPacketUpdateHorseName));
peer->Encode(&packet, sizeof(TPacketUpdateHorseName));
}

View File

@ -0,0 +1,544 @@
#include "stdafx.h"
#include "ClientManager.h"
#include "Main.h"
#include "Config.h"
#include "QID.h"
#include "Cache.h"
extern std::string g_stLocale;
extern bool CreatePlayerTableFromRes(MYSQL_RES * res, TPlayerTable * pkTab);
extern int g_test_server;
extern int g_log;
bool CClientManager::InsertLogonAccount(const char * c_pszLogin, DWORD dwHandle, const char * c_pszIP)
{
char szLogin[LOGIN_MAX_LEN + 1];
trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin));
itertype(m_map_kLogonAccount) it = m_map_kLogonAccount.find(szLogin);
if (m_map_kLogonAccount.end() != it)
return false;
CLoginData * pkLD = GetLoginDataByLogin(c_pszLogin);
if (!pkLD)
return false;
pkLD->SetConnectedPeerHandle(dwHandle);
pkLD->SetIP(c_pszIP);
m_map_kLogonAccount.insert(TLogonAccountMap::value_type(szLogin, pkLD));
return true;
}
bool CClientManager::DeleteLogonAccount(const char * c_pszLogin, DWORD dwHandle)
{
char szLogin[LOGIN_MAX_LEN + 1];
trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin));
itertype(m_map_kLogonAccount) it = m_map_kLogonAccount.find(szLogin);
if (it == m_map_kLogonAccount.end())
return false;
CLoginData * pkLD = it->second;
if (pkLD->GetConnectedPeerHandle() != dwHandle)
{
sys_err("%s tried to logout in other peer handle %lu, current handle %lu", szLogin, dwHandle, pkLD->GetConnectedPeerHandle());
return false;
}
if (pkLD->IsPlay())
{
pkLD->SetPlay(false);
SendLoginToBilling(pkLD, false);
}
if (pkLD->IsDeleted())
{
delete pkLD;
}
m_map_kLogonAccount.erase(it);
return true;
}
bool CClientManager::FindLogonAccount(const char * c_pszLogin)
{
char szLogin[LOGIN_MAX_LEN + 1];
trim_and_lower(c_pszLogin, szLogin, sizeof(szLogin));
if (m_map_kLogonAccount.end() == m_map_kLogonAccount.find(szLogin))
return false;
return true;
}
void CClientManager::QUERY_LOGIN_BY_KEY(CPeer * pkPeer, DWORD dwHandle, TPacketGDLoginByKey * p)
{
#ifdef ENABLE_LIMIT_TIME
static int s_updateCount = 0;
static int s_curTime = time(0);
if (s_updateCount > 100)
{
s_curTime = time(0);
s_updateCount = 0;
}
++s_updateCount;
if (s_curTime >= GLOBAL_LIMIT_TIME)
{
sys_err("Server life time expired.");
exit(0);
return;
}
#endif
CLoginData * pkLoginData = GetLoginData(p->dwLoginKey);
char szLogin[LOGIN_MAX_LEN + 1];
trim_and_lower(p->szLogin, szLogin, sizeof(szLogin));
if (!pkLoginData)
{
sys_log(0, "LOGIN_BY_KEY key not exist %s %lu", szLogin, p->dwLoginKey);
pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle);
return;
}
TAccountTable & r = pkLoginData->GetAccountRef();
if (FindLogonAccount(r.login))
{
sys_log(0, "LOGIN_BY_KEY already login %s %lu", r.login, p->dwLoginKey);
TPacketDGLoginAlready ptog;
strlcpy(ptog.szLogin, szLogin, sizeof(ptog.szLogin));
pkPeer->EncodeHeader(HEADER_DG_LOGIN_ALREADY, dwHandle, sizeof(TPacketDGLoginAlready));
pkPeer->Encode(&ptog, sizeof(TPacketDGLoginAlready));
return;
}
if (strcasecmp(r.login, szLogin))
{
sys_log(0, "LOGIN_BY_KEY login differ %s %lu input %s", r.login, p->dwLoginKey, szLogin);
pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle);
return;
}
if (memcmp(pkLoginData->GetClientKey(), p->adwClientKey, sizeof(DWORD) * 4))
{
const DWORD * pdwClientKey = pkLoginData->GetClientKey();
sys_log(0, "LOGIN_BY_KEY client key differ %s %lu %lu %lu %lu, %lu %lu %lu %lu",
r.login,
p->adwClientKey[0], p->adwClientKey[1], p->adwClientKey[2], p->adwClientKey[3],
pdwClientKey[0], pdwClientKey[1], pdwClientKey[2], pdwClientKey[3]);
pkPeer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, dwHandle);
return;
}
TAccountTable * pkTab = new TAccountTable;
memset(pkTab, 0, sizeof(TAccountTable));
pkTab->id = r.id;
trim_and_lower(r.login, pkTab->login, sizeof(pkTab->login));
strlcpy(pkTab->passwd, r.passwd, sizeof(pkTab->passwd));
strlcpy(pkTab->social_id, r.social_id, sizeof(pkTab->social_id));
strlcpy(pkTab->status, "OK", sizeof(pkTab->status));
ClientHandleInfo * info = new ClientHandleInfo(dwHandle);
info->pAccountTable = pkTab;
strlcpy(info->ip, p->szIP, sizeof(info->ip));
sys_log(0, "LOGIN_BY_KEY success %s %lu %s", r.login, p->dwLoginKey, info->ip);
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), r.id);
CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info);
}
void CClientManager::RESULT_LOGIN_BY_KEY(CPeer * peer, SQLMsg * msg)
{
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData;
if (msg->uiSQLErrno != 0)
{
peer->EncodeReturn(HEADER_DG_LOGIN_NOT_EXIST, info->dwHandle);
delete info;
return;
}
char szQuery[QUERY_MAX_LEN];
if (msg->Get()->uiNumRows == 0)
{
DWORD account_id = info->pAccountTable->id;
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(), account_id);
std::auto_ptr<SQLMsg> pMsg(CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER));
sys_log(0, "RESULT_LOGIN_BY_KEY FAIL player_index's NULL : ID:%d", account_id);
if (pMsg->Get()->uiNumRows == 0)
{
sys_log(0, "RESULT_LOGIN_BY_KEY FAIL player_index's NULL : ID:%d", account_id);
// PLAYER_INDEX_CREATE_BUG_FIX
//snprintf(szQuery, sizeof(szQuery), "INSERT IGNORE INTO player_index%s (id) VALUES(%lu)", GetTablePostfix(), info->pAccountTable->id);
snprintf(szQuery, sizeof(szQuery), "INSERT INTO player_index%s (id) VALUES(%u)", GetTablePostfix(), info->pAccountTable->id);
CDBManager::instance().ReturnQuery(szQuery, QID_PLAYER_INDEX_CREATE, peer->GetHandle(), info);
// END_PLAYER_INDEX_CREATE_BUF_FIX
}
return;
}
MYSQL_ROW row = mysql_fetch_row(msg->Get()->pSQLResult);
int col = 0;
for (; col < PLAYER_PER_ACCOUNT; ++col)
str_to_number(info->pAccountTable->players[col].dwID, row[col]);
str_to_number(info->pAccountTable->bEmpire, row[col++]);
info->account_index = 1;
extern std::string g_stLocale;
if (g_stLocale == "gb2312")
{
snprintf(szQuery, sizeof(szQuery),
"SELECT id, name, job, level, alignment, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player%s WHERE account_id=%u",
GetTablePostfix(), info->pAccountTable->id);
}
else
{
snprintf(szQuery, sizeof(szQuery),
"SELECT id, name, job, level, playtime, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player%s WHERE account_id=%u",
GetTablePostfix(), info->pAccountTable->id);
}
CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN, peer->GetHandle(), info);
}
// PLAYER_INDEX_CREATE_BUG_FIX
void CClientManager::RESULT_PLAYER_INDEX_CREATE(CPeer * pkPeer, SQLMsg * msg)
{
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData;
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery), "SELECT pid1, pid2, pid3, pid4, empire FROM player_index%s WHERE id=%u", GetTablePostfix(),
info->pAccountTable->id);
CDBManager::instance().ReturnQuery(szQuery, QID_LOGIN_BY_KEY, pkPeer->GetHandle(), info);
}
// END_PLAYER_INDEX_CREATE_BUG_FIX
TAccountTable * CreateAccountTableFromRes(MYSQL_RES * res)
{
char input_pwd[PASSWD_MAX_LEN + 1];
MYSQL_ROW row = NULL;
DWORD col;
row = mysql_fetch_row(res);
col = 0;
TAccountTable * pkTab = new TAccountTable;
memset(pkTab, 0, sizeof(TAccountTable));
// ù<><C3B9>° <20>÷<EFBFBD> <20>͸<EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD> (JOIN QUERY<52><59> <20><><EFBFBD><EFBFBD> <20><> <20><>)
strlcpy(input_pwd, row[col++], sizeof(input_pwd));
str_to_number(pkTab->id, row[col++]);
strlcpy(pkTab->login, row[col++], sizeof(pkTab->login));
strlcpy(pkTab->passwd, row[col++], sizeof(pkTab->passwd));
strlcpy(pkTab->social_id, row[col++], sizeof(pkTab->social_id));
str_to_number(pkTab->bEmpire, row[col++]);
for (int j = 0; j < PLAYER_PER_ACCOUNT; ++j)
str_to_number(pkTab->players[j].dwID, row[col++]);
strlcpy(pkTab->status, row[col++], sizeof(pkTab->status));
if (strcmp(pkTab->passwd, input_pwd))
{
delete pkTab;
return NULL;
}
return pkTab;
}
void CreateAccountPlayerDataFromRes(MYSQL_RES * pRes, TAccountTable * pkTab)
{
if (!pRes)
return;
for (DWORD i = 0; i < mysql_num_rows(pRes); ++i)
{
MYSQL_ROW row = mysql_fetch_row(pRes);
int col = 0;
DWORD player_id = 0;
!row[col++] ? 0 : str_to_number(player_id, row[col - 1]);
if (!player_id)
continue;
int j;
for (j = 0; j < PLAYER_PER_ACCOUNT; ++j)
{
if (pkTab->players[j].dwID == player_id)
{
CPlayerTableCache * pc = CClientManager::instance().GetPlayerCache(player_id);
TPlayerTable * pt = pc ? pc->Get(false) : NULL;
if (pt)
{
strlcpy(pkTab->players[j].szName, pt->name, sizeof(pkTab->players[j].szName));
pkTab->players[j].byJob = pt->job;
pkTab->players[j].byLevel = pt->level;
pkTab->players[j].dwPlayMinutes = pt->playtime;
pkTab->players[j].byST = pt->st;
pkTab->players[j].byHT = pt->ht;
pkTab->players[j].byDX = pt->dx;
pkTab->players[j].byIQ = pt->iq;
pkTab->players[j].wMainPart = pt->parts[PART_MAIN];
pkTab->players[j].wHairPart = pt->parts[PART_HAIR];
pkTab->players[j].x = pt->x;
pkTab->players[j].y = pt->y;
pkTab->players[j].skill_group = pt->skill_group;
pkTab->players[j].bChangeName = 0;
}
else
{
if (!row[col++])
*pkTab->players[j].szName = '\0';
else
strlcpy(pkTab->players[j].szName, row[col - 1], sizeof(pkTab->players[j].szName));
pkTab->players[j].byJob = 0;
pkTab->players[j].byLevel = 0;
pkTab->players[j].dwPlayMinutes = 0;
pkTab->players[j].byST = 0;
pkTab->players[j].byHT = 0;
pkTab->players[j].byDX = 0;
pkTab->players[j].byIQ = 0;
pkTab->players[j].wMainPart = 0;
pkTab->players[j].wHairPart = 0;
pkTab->players[j].x = 0;
pkTab->players[j].y = 0;
pkTab->players[j].skill_group = 0;
pkTab->players[j].bChangeName = 0;
str_to_number(pkTab->players[j].byJob, row[col++]);
str_to_number(pkTab->players[j].byLevel, row[col++]);
str_to_number(pkTab->players[j].dwPlayMinutes, row[col++]);
str_to_number(pkTab->players[j].byST, row[col++]);
str_to_number(pkTab->players[j].byHT, row[col++]);
str_to_number(pkTab->players[j].byDX, row[col++]);
str_to_number(pkTab->players[j].byIQ, row[col++]);
str_to_number(pkTab->players[j].wMainPart, row[col++]);
str_to_number(pkTab->players[j].wHairPart, row[col++]);
str_to_number(pkTab->players[j].x, row[col++]);
str_to_number(pkTab->players[j].y, row[col++]);
str_to_number(pkTab->players[j].skill_group, row[col++]);
str_to_number(pkTab->players[j].bChangeName, row[col++]);
}
sys_log(0, "%s %lu %lu hair %u",
pkTab->players[j].szName, pkTab->players[j].x, pkTab->players[j].y, pkTab->players[j].wHairPart);
break;
}
}
/*
if (j == PLAYER_PER_ACCOUNT)
sys_err("cannot find player_id on this account (login: %s id %lu account %lu %lu %lu)",
pkTab->login, player_id,
pkTab->players[0].dwID,
pkTab->players[1].dwID,
pkTab->players[2].dwID);
*/
}
}
void CClientManager::RESULT_LOGIN(CPeer * peer, SQLMsg * msg)
{
CQueryInfo * qi = (CQueryInfo *) msg->pvUserData;
ClientHandleInfo * info = (ClientHandleInfo *) qi->pvData;
if (info->account_index == 0)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>?
if (msg->Get()->uiNumRows == 0)
{
sys_log(0, "RESULT_LOGIN: no account");
peer->EncodeHeader(HEADER_DG_LOGIN_NOT_EXIST, info->dwHandle, 0);
delete info;
return;
}
info->pAccountTable = CreateAccountTableFromRes(msg->Get()->pSQLResult);
if (!info->pAccountTable)
{
sys_log(0, "RESULT_LOGIN: no account : WRONG_PASSWD");
peer->EncodeReturn(HEADER_DG_LOGIN_WRONG_PASSWD, info->dwHandle);
delete info;
}
else
{
++info->account_index;
char queryStr[512];
extern std::string g_stLocale;
if (g_stLocale == "gb2312")
{
snprintf(queryStr, sizeof(queryStr),
"SELECT id, name, job, level, alignment, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player%s WHERE account_id=%u",
GetTablePostfix(), info->pAccountTable->id);
}
else
{
snprintf(queryStr, sizeof(queryStr),
"SELECT id, name, job, level, playtime, st, ht, dx, iq, part_main, part_hair, x, y, skill_group, change_name FROM player%s WHERE account_id=%u",
GetTablePostfix(), info->pAccountTable->id);
}
CDBManager::instance().ReturnQuery(queryStr, QID_LOGIN, peer->GetHandle(), info);
}
return;
}
else
{
if (!info->pAccountTable) // <20>̷<EFBFBD><CCB7><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>;;
{
peer->EncodeReturn(HEADER_DG_LOGIN_WRONG_PASSWD, info->dwHandle);
delete info;
return;
}
// <20>ٸ<EFBFBD> <20><><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD> <20>̹<EFBFBD> <20>α<EFBFBD><CEB1><EFBFBD> <20>ع<EFBFBD><D8B9>ȴٸ<C8B4>.. <20>̹<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ߴٰ<DFB4> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
if (!InsertLogonAccount(info->pAccountTable->login, peer->GetHandle(), info->ip))
{
sys_log(0, "RESULT_LOGIN: already logon %s", info->pAccountTable->login);
TPacketDGLoginAlready p;
strlcpy(p.szLogin, info->pAccountTable->login, sizeof(p.szLogin));
peer->EncodeHeader(HEADER_DG_LOGIN_ALREADY, info->dwHandle, sizeof(TPacketDGLoginAlready));
peer->Encode(&p, sizeof(p));
}
else
{
sys_log(0, "RESULT_LOGIN: login success %s rows: %lu", info->pAccountTable->login, msg->Get()->uiNumRows);
if (msg->Get()->uiNumRows > 0)
CreateAccountPlayerDataFromRes(msg->Get()->pSQLResult, info->pAccountTable);
//PREVENT_COPY_ITEM
CLoginData * p = GetLoginDataByLogin(info->pAccountTable->login);
memcpy(&p->GetAccountRef(), info->pAccountTable, sizeof(TAccountTable));
//END_PREVENT_COPY_ITEM
peer->EncodeHeader(HEADER_DG_LOGIN_SUCCESS, info->dwHandle, sizeof(TAccountTable));
peer->Encode(info->pAccountTable, sizeof(TAccountTable));
}
delete info->pAccountTable;
info->pAccountTable = NULL;
delete info;
}
}
void CClientManager::QUERY_LOGOUT(CPeer * peer, DWORD dwHandle,const char * data)
{
TLogoutPacket* packet = (TLogoutPacket*)data;
if (!*packet->login)
return;
CLoginData * pLoginData = GetLoginDataByLogin(packet->login);
if (pLoginData == NULL)
return;
int pid[PLAYER_PER_ACCOUNT];
for (int n = 0; n < PLAYER_PER_ACCOUNT; ++n)
{
if (pLoginData->GetAccountRef().players[n].dwID == 0)
{
if (g_test_server)
sys_log(0, "LOGOUT %s %d", packet->login, pLoginData->GetAccountRef().players[n].dwID);
continue;
}
pid[n] = pLoginData->GetAccountRef().players[n].dwID;
if (g_log)
sys_log(0, "LOGOUT InsertLogoutPlayer %s %d", packet->login, pid[n]);
InsertLogoutPlayer(pid[n]);
}
if (DeleteLogonAccount(packet->login, peer->GetHandle()))
{
if (g_log)
sys_log(0, "LOGOUT %s ", packet->login);
}
}
void CClientManager::QUERY_CHANGE_NAME(CPeer * peer, DWORD dwHandle, TPacketGDChangeName * p)
{
char queryStr[QUERY_MAX_LEN];
if (g_stLocale == "sjis")
snprintf(queryStr, sizeof(queryStr),
"SELECT COUNT(*) as count FROM player%s WHERE name='%s' collate sjis_japanese_ci AND id <> %u",
GetTablePostfix(), p->name, p->pid);
else
snprintf(queryStr, sizeof(queryStr),
"SELECT COUNT(*) as count FROM player%s WHERE name='%s' AND id <> %u", GetTablePostfix(), p->name, p->pid);
std::auto_ptr<SQLMsg> pMsg(CDBManager::instance().DirectQuery(queryStr, SQL_PLAYER));
if (pMsg->Get()->uiNumRows)
{
if (!pMsg->Get()->pSQLResult)
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
return;
}
MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
if (*row[0] != '0')
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_ALREADY, dwHandle, 0);
return;
}
}
else
{
peer->EncodeHeader(HEADER_DG_PLAYER_CREATE_FAILED, dwHandle, 0);
return;
}
snprintf(queryStr, sizeof(queryStr),
"UPDATE player%s SET name='%s',change_name=0 WHERE id=%u", GetTablePostfix(), p->name, p->pid);
std::auto_ptr<SQLMsg> pMsg0(CDBManager::instance().DirectQuery(queryStr, SQL_PLAYER));
TPacketDGChangeName pdg;
peer->EncodeHeader(HEADER_DG_CHANGE_NAME, dwHandle, sizeof(TPacketDGChangeName));
pdg.pid = p->pid;
strlcpy(pdg.name, p->name, sizeof(pdg.name));
peer->Encode(&pdg, sizeof(TPacketDGChangeName));
}

View File

@ -0,0 +1,135 @@
// vim:ts=4 sw=4
#include "stdafx.h"
#include "ClientManager.h"
#include "Config.h"
#include "DBManager.h"
#include "QID.h"
void CClientManager::QUERY_PARTY_CREATE(CPeer* peer, TPacketPartyCreate* p)
{
TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()];
if (pm.find(p->dwLeaderPID) == pm.end())
{
pm.insert(make_pair(p->dwLeaderPID, TPartyMember()));
ForwardPacket(HEADER_DG_PARTY_CREATE, p, sizeof(TPacketPartyCreate), peer->GetChannel(), peer);
sys_log(0, "PARTY Create [%lu]", p->dwLeaderPID);
}
else
{
sys_err("PARTY Create - Already exists [%lu]", p->dwLeaderPID);
}
}
void CClientManager::QUERY_PARTY_DELETE(CPeer* peer, TPacketPartyDelete* p)
{
TPartyMap& pm = m_map_pkChannelParty[peer->GetChannel()];
itertype(pm) it = pm.find(p->dwLeaderPID);
if (it == pm.end())
{
sys_err("PARTY Delete - Non exists [%lu]", p->dwLeaderPID);
return;
}
pm.erase(it);
ForwardPacket(HEADER_DG_PARTY_DELETE, p, sizeof(TPacketPartyDelete), peer->GetChannel(), peer);
sys_log(0, "PARTY Delete [%lu]", p->dwLeaderPID);
}
void CClientManager::QUERY_PARTY_ADD(CPeer* peer, TPacketPartyAdd* p)
{
TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()];
itertype(pm) it = pm.find(p->dwLeaderPID);
if (it == pm.end())
{
sys_err("PARTY Add - Non exists [%lu]", p->dwLeaderPID);
return;
}
if (it->second.find(p->dwPID) == it->second.end())
{
it->second.insert(std::make_pair(p->dwPID, TPartyInfo()));
ForwardPacket(HEADER_DG_PARTY_ADD, p, sizeof(TPacketPartyAdd), peer->GetChannel(), peer);
sys_log(0, "PARTY Add [%lu] to [%lu]", p->dwPID, p->dwLeaderPID);
}
else
sys_err("PARTY Add - Already [%lu] in party [%lu]", p->dwPID, p->dwLeaderPID);
}
void CClientManager::QUERY_PARTY_REMOVE(CPeer* peer, TPacketPartyRemove* p)
{
TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()];
itertype(pm) it = pm.find(p->dwLeaderPID);
if (it == pm.end())
{
sys_err("PARTY Remove - Non exists [%lu] cannot remove [%lu]",p->dwLeaderPID, p->dwPID);
return;
}
itertype(it->second) pit = it->second.find(p->dwPID);
if (pit != it->second.end())
{
it->second.erase(pit);
ForwardPacket(HEADER_DG_PARTY_REMOVE, p, sizeof(TPacketPartyRemove), peer->GetChannel(), peer);
sys_log(0, "PARTY Remove [%lu] to [%lu]", p->dwPID, p->dwLeaderPID);
}
else
sys_err("PARTY Remove - Cannot find [%lu] in party [%lu]", p->dwPID, p->dwLeaderPID);
}
void CClientManager::QUERY_PARTY_STATE_CHANGE(CPeer* peer, TPacketPartyStateChange* p)
{
TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()];
itertype(pm) it = pm.find(p->dwLeaderPID);
if (it == pm.end())
{
sys_err("PARTY StateChange - Non exists [%lu] cannot state change [%lu]",p->dwLeaderPID, p->dwPID);
return;
}
itertype(it->second) pit = it->second.find(p->dwPID);
if (pit == it->second.end())
{
sys_err("PARTY StateChange - Cannot find [%lu] in party [%lu]", p->dwPID, p->dwLeaderPID);
return;
}
if (p->bFlag)
pit->second.bRole = p->bRole;
else
pit->second.bRole = 0;
ForwardPacket(HEADER_DG_PARTY_STATE_CHANGE, p, sizeof(TPacketPartyStateChange), peer->GetChannel(), peer);
sys_log(0, "PARTY StateChange [%lu] at [%lu] from %d %d",p->dwPID, p->dwLeaderPID, p->bRole, p->bFlag);
}
void CClientManager::QUERY_PARTY_SET_MEMBER_LEVEL(CPeer* peer, TPacketPartySetMemberLevel* p)
{
TPartyMap & pm = m_map_pkChannelParty[peer->GetChannel()];
itertype(pm) it = pm.find(p->dwLeaderPID);
if (it == pm.end())
{
sys_err("PARTY SetMemberLevel - Non exists [%lu] cannot level change [%lu]",p->dwLeaderPID, p->dwPID);
return;
}
itertype(it->second) pit = it->second.find(p->dwPID);
if (pit == it->second.end())
{
sys_err("PARTY SetMemberLevel - Cannot find [%lu] in party [%lu]", p->dwPID, p->dwLeaderPID);
return;
}
pit->second.bLevel = p->bLevel;
ForwardPacket(HEADER_DG_PARTY_SET_MEMBER_LEVEL, p, sizeof(TPacketPartySetMemberLevel), peer->GetChannel());
sys_log(0, "PARTY SetMemberLevel pid [%lu] level %d",p->dwPID, p->bLevel);
}

File diff suppressed because it is too large Load Diff

250
db/src/Config.cpp Normal file
View File

@ -0,0 +1,250 @@
#include "stdafx.h"
#include "Config.h"
CConfig::CConfig()
{
}
CConfig::~CConfig()
{
Destroy();
}
void CConfig::Destroy()
{
m_valueMap.clear();
}
void CConfig::NextLine(FILE *fp)
{
int c;
while ((c = fgetc(fp)) != EOF)
{
if (c == '\n')
return;
}
}
bool CConfig::GetWord(FILE *fp, char *tar)
{
int i = 0;
int c;
int semicolon_mode = 0;
while ((c = fgetc(fp)) != EOF)
{
if (c == 13)
continue;
if (semicolon_mode)
{
if (c == '"')
{
tar[i] = '\0';
return true;
}
tar[i++] = c;
continue;
}
else
{
if (i == 0)
{
if (c == '"')
{
semicolon_mode = 1;
continue;
}
if (c == ' ' || c == '\t' || c == '\n')
{
continue;
}
}
if ((c == ' ' || c == '\t' || c == '\n'))
{
// <20><>.
tar[i] = '\0';
return true;
}
tar[i] = c;
++i;
}
}
return (i != 0);
}
bool CConfig::GetLine(FILE* fp, char*dest)
{
int c;
int i = 0;
while ((c = fgetc(fp)) != EOF)
{
if (c == '\n')
return true;
dest[i] = c;
++i;
}
return true;
}
bool CConfig::LoadFile(const char* filename)
{
char szTmp[256];
char comment[256];
FILE * fp = fopen(filename, "rb");
if (fp == NULL)
return false;
int mode = 0;
while (GetWord(fp, szTmp))
{
if (strcmp(szTmp, "//") == 0)
{
NextLine(fp);
continue;
}
switch (mode)
{
case 0:
strlcpy(comment, szTmp, sizeof(comment));
++mode;
break;
case 1:
if (*szTmp == '=')
++mode;
break;
case 2:
mode = 0;
m_valueMap.insert(TValueMap::value_type(comment, szTmp));
break;
}
// ITEM_ID_RANGE
if (mode == 2 && strcmp(comment, "ITEM_ID_RANGE") == 0)
{
GetLine(fp, szTmp);
m_valueMap.insert(TValueMap::value_type(comment, szTmp));
mode = 0;
}
// ITEM_ID_RANGE_END
}
// <20><><EFBFBD><EFBFBD> <20>ݴ<EFBFBD> <20>κ<EFBFBD>.
fclose(fp);
return true;
}
std::string * CConfig::Search(const char* key)
{
itertype(m_valueMap) i = m_valueMap.find(key);
if (i == m_valueMap.end())
return NULL;
else
return (&i->second);
}
bool CConfig::GetParam(const char*key, int index, DWORD *Param)
{
std::string * pstStr = Search(key);
if (!pstStr)
return false;
char szParam[5][32];
sscanf(pstStr->c_str(), "%s %s %s %s %s", szParam[0],szParam[1],szParam[2],szParam[3],szParam[4]);
str_to_number(*Param, szParam[index]);
sys_log(0, "GetParam %d", *Param);
return true;
}
const char * CConfig::Get(const char* key)
{
std::string * pstStr = Search(key);
if (!pstStr)
{
static std::string stTemp = "";
return stTemp.c_str();
}
return pstStr->c_str();
}
bool CConfig::GetValue(const char * key, int* dest)
{
if (!Search(key))
return false;
str_to_number(*dest, Get(key));
return true;
}
bool CConfig::GetValue(const char * key, float *dest)
{
if (!Search(key))
return false;
str_to_number(*dest, Get(key));
return true;
}
bool CConfig::GetValue(const char * key, DWORD *dest)
{
if (!Search(key))
return false;
str_to_number(*dest, Get(key));
return true;
}
bool CConfig::GetValue(const char * key, BYTE *dest)
{
if (!Search(key))
return false;
*dest = *(BYTE *) Get(key);
return true;
}
bool CConfig::GetValue(const char * key, char *dest, size_t destSize)
{
if (!Search(key))
return false;
strlcpy(dest, Get(key), destSize);
if (!*dest)
return false;
return true;
}
bool CConfig::GetTwoValue(const char* key, DWORD * dest1, DWORD *dest2)
{
if (!GetParam(key, 0, dest1))
return false;
if (!GetParam(key, 1, dest2))
return false;
return true;
}

34
db/src/Config.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef __INC_CONFIG_H__
#define __INC_CONFIG_H__
typedef std::map<std::string, std::string> TValueMap;
class CConfig : public singleton<CConfig>
{
public:
CConfig();
~CConfig();
bool LoadFile(const char* filename);
bool GetValue(const char* key, int* dest);
bool GetValue(const char* key, float* dest);
bool GetValue(const char* key, DWORD* dest);
bool GetValue(const char* key, BYTE* dest);
bool GetValue(const char* key, char* dest, size_t destSize);
bool GetWord(FILE* fp, char* dest);
bool GetLine(FILE* fp, char* dest);
bool GetTwoValue(const char* key, DWORD * dest1, DWORD *dest2);
void NextLine(FILE* fp);
private:
void Destroy();
bool GetParam(const char*key,int index, DWORD *Param);
const char * Get(const char* key);
std::string * Search(const char* key);
private:
TValueMap m_valueMap;
};
#endif

430
db/src/CsvReader.cpp Normal file
View File

@ -0,0 +1,430 @@
#include "stdafx.h"
#include "CsvReader.h"
#include <fstream>
#include <algorithm>
#ifndef Assert
#include <assert.h>
#define Assert assert
#define LogToFile (void)(0);
#endif
namespace
{
/// <20>Ľ̿<C4BD> state <20><><EFBFBD>Ű<EFBFBD>
enum ParseState
{
STATE_NORMAL = 0, ///< <20>Ϲ<EFBFBD> <20><><EFBFBD><EFBFBD>
STATE_QUOTE ///< <20><><EFBFBD><EFBFBD>ǥ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
};
/// <20><><EFBFBD>ڿ<EFBFBD> <20>¿<EFBFBD><C2BF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
std::string Trim(std::string str)
{
str = str.erase(str.find_last_not_of(" \t\r\n") + 1);
str = str.erase(0, str.find_first_not_of(" \t\r\n"));
return str;
}
/// \brief <20>־<EFBFBD><D6BE><EFBFBD> <20><><EFBFBD><20>ִ<EFBFBD> <20><><EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ҹ<EFBFBD><D2B9>ڷ<EFBFBD> <20>ٲ۴<D9B2>.
std::string Lower(std::string original)
{
std::transform(original.begin(), original.end(), original.begin(), tolower);
return original;
}
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD> <20><>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
/// \param name <20><> <20≯<EFBFBD>
/// \param index <20><> <20>ε<EFBFBD><CEB5><EFBFBD>
////////////////////////////////////////////////////////////////////////////////
void cCsvAlias::AddAlias(const char* name, size_t index)
{
std::string converted(Lower(name));
Assert(m_Name2Index.find(converted) == m_Name2Index.end());
Assert(m_Index2Name.find(index) == m_Index2Name.end());
m_Name2Index.insert(NAME2INDEX_MAP::value_type(converted, index));
m_Index2Name.insert(INDEX2NAME_MAP::value_type(index, name));
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
////////////////////////////////////////////////////////////////////////////////
void cCsvAlias::Destroy()
{
m_Name2Index.clear();
m_Index2Name.clear();
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param index <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD>
/// \return const char* <20≯<EFBFBD>
////////////////////////////////////////////////////////////////////////////////
const char* cCsvAlias::operator [] (size_t index) const
{
INDEX2NAME_MAP::const_iterator itr(m_Index2Name.find(index));
if (itr == m_Index2Name.end())
{
LogToFile(NULL, "cannot find suitable conversion for %d", index);
Assert(false && "cannot find suitable conversion");
return NULL;
}
return itr->second.c_str();
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20≯<EFBFBD><CCB8><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param name <20≯<EFBFBD>
/// \return size_t <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD>
////////////////////////////////////////////////////////////////////////////////
size_t cCsvAlias::operator [] (const char* name) const
{
NAME2INDEX_MAP::const_iterator itr(m_Name2Index.find(Lower(name)));
if (itr == m_Name2Index.end())
{
LogToFile(NULL, "cannot find suitable conversion for %s", name);
Assert(false && "cannot find suitable conversion");
return 0;
}
return itr->second;
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> CSV <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>Ѵ<EFBFBD>.
/// \param fileName CSV <20><><EFBFBD><EFBFBD> <20≯<EFBFBD>
/// \param seperator <20>ʵ<EFBFBD> <20>и<EFBFBD><D0B8>ڷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> ','<27>̴<EFBFBD>.
/// \param quote <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> '"'<27>̴<EFBFBD>.
/// \return bool <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ߴٸ<DFB4> true, <20>ƴ϶<C6B4><CFB6><EFBFBD> false
////////////////////////////////////////////////////////////////////////////////
bool cCsvFile::Load(const char* fileName, const char seperator, const char quote)
{
Assert(seperator != quote);
std::ifstream file(fileName, std::ios::in);
if (!file) return false;
Destroy(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD>
cCsvRow* row = NULL;
ParseState state = STATE_NORMAL;
std::string token = "";
char buf[2048+1] = {0,};
while (file.good())
{
file.getline(buf, 2048);
buf[sizeof(buf)-1] = 0;
std::string line(Trim(buf));
if (line.empty() || (state == STATE_NORMAL && line[0] == '#')) continue;
std::string text = std::string(line) + " "; // <20>Ľ<EFBFBD> lookahead <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٿ<EFBFBD><D9BF>ش<EFBFBD>.
size_t cur = 0;
while (cur < text.size())
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>尡 QUOTE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>,
if (state == STATE_QUOTE)
{
// '"' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD>.
// 1. <20><> <20><><EFBFBD>ο<EFBFBD> Ư<><C6AF> <20><><EFBFBD>ڰ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20≯<EFBFBD> <20>˸<EFBFBD><CBB8><EFBFBD> <20><> <20>¿<EFBFBD><C2BF><EFBFBD> <20><>
// 2. <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '"' <20><><EFBFBD>ڰ<EFBFBD> '"' 2<><32><EFBFBD><EFBFBD> ġȯ<C4A1><C8AF> <20><>
// <20><> <20><> ù<><C3B9>° <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> CSV <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD><CCB6><EFBFBD>,
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> STATE_NORMAL<41><4C> <20>ɸ<EFBFBD><C9B8><EFBFBD> <20>Ǿ<EFBFBD><C7BE>ִ<EFBFBD>.
// <20>׷<EFBFBD><D7B7>Ƿ<EFBFBD> <20><><EFBFBD><20>ɸ<EFBFBD><C9B8><EFBFBD> <20><><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>쳪, 2<><32> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̴<EFBFBD>.
// 2<><32><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><ECBFA1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '"' <20><><EFBFBD>ڰ<EFBFBD> 2<><32><EFBFBD><EFBFBD> <20><>Ÿ<EFBFBD><C5B8><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><ECBFA1> <20>ƴϴ<C6B4>. <20≯<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ؼ<EFBFBD> <20>ڵ带 ¥<><C2A5>...
if (text[cur] == quote)
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڰ<EFBFBD> '"' <20><><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD>, <20><> <20><><EFBFBD>ӵ<EFBFBD> '"' <20><><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD>
// <20>̴<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '"' <20><><EFBFBD>ڰ<EFBFBD> ġȯ<C4A1><C8AF> <20><><EFBFBD>̴<EFBFBD>.
if (text[cur+1] == quote)
{
token += quote;
++cur;
}
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڰ<EFBFBD> '"' <20><><EFBFBD>ڰ<EFBFBD> <20>ƴ϶<C6B4><CFB6><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '"'<27><><EFBFBD>ڴ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>˸<EFBFBD><CBB8><EFBFBD> <20><><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD> <20><> <20><> <20>ִ<EFBFBD>.
else
{
state = STATE_NORMAL;
}
}
else
{
token += text[cur];
}
}
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>尡 NORMAL <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>,
else if (state == STATE_NORMAL)
{
if (row == NULL)
row = new cCsvRow();
// ',' <20><><EFBFBD>ڸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ǹ<EFBFBD><C7B9>Ѵ<EFBFBD>.
// <20><>ū<EFBFBD><C5AB><EFBFBD>μ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD>ٰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ְ<EFBFBD>, <20><>ū<EFBFBD><C5AB> <20>ʱ<EFBFBD>ȭ<EFBFBD>Ѵ<EFBFBD>.
if (text[cur] == seperator)
{
row->push_back(token);
token.clear();
}
// '"' <20><><EFBFBD>ڸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD>, QUOTE <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
else if (text[cur] == quote)
{
state = STATE_QUOTE;
}
// <20>ٸ<EFBFBD> <20>Ϲ<EFBFBD> <20><><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ū<EFBFBD><C5AB><EFBFBD>ٰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD>.
else
{
token += text[cur];
}
}
++cur;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ',' <20><><EFBFBD>ڰ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20>߰<EFBFBD><DFB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
// <20><>, ó<><C3B3><EFBFBD><EFBFBD> <20>Ľ<EFBFBD> lookahead <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
if (state == STATE_NORMAL)
{
Assert(row != NULL);
row->push_back(token.substr(0, token.size()-2));
m_Rows.push_back(row);
token.clear();
row = NULL;
}
else
{
token = token.substr(0, token.size()-2) + "\r\n";
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CSV <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
/// \param fileName CSV <20><><EFBFBD><EFBFBD> <20≯<EFBFBD>
/// \param append true<75><65> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD>. false<73><65> <20><><EFBFBD><EFBFBD><ECBFA1>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
/// \param seperator <20>ʵ<EFBFBD> <20>и<EFBFBD><D0B8>ڷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> ','<27>̴<EFBFBD>.
/// \param quote <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> '"'<27>̴<EFBFBD>.
/// \return bool <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ߴٸ<DFB4> true, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><ECBFA1> false
////////////////////////////////////////////////////////////////////////////////
bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quote) const
{
Assert(seperator != quote);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>÷<EFBFBD><C3B7>׷<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
std::ofstream file;
if (append) { file.open(fileName, std::ios::out | std::ios::app); }
else { file.open(fileName, std::ios::out | std::ios::trunc); }
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ߴٸ<DFB4>, false<73><65> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
if (!file) return false;
char special_chars[5] = { seperator, quote, '\r', '\n', 0 };
char quote_escape_string[3] = { quote, quote, 0 };
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Ⱦ<><C8BE><EFBFBD>ϸ鼭...
for (size_t i=0; i<m_Rows.size(); i++)
{
const cCsvRow& row = *((*this)[i]);
std::string line;
// <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ū<EFBFBD><C5AB> Ⱦ<><C8BE><EFBFBD>ϸ鼭...
for (size_t j=0; j<row.size(); j++)
{
const std::string& token = row[j];
// <20>Ϲ<EFBFBD><CFB9><EFBFBD><EFBFBD><EFBFBD>('"' <20>Ǵ<EFBFBD> ','<27><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
// <20><>ū<EFBFBD>̶<EFBFBD><CCB6><EFBFBD> <20>׳<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> <20>ȴ<EFBFBD>.
if (token.find_first_of(special_chars) == std::string::npos)
{
line += token;
}
// Ư<><C6AF><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ū<EFBFBD>̶<EFBFBD><CCB6><EFBFBD> <20><><EFBFBD>ڿ<EFBFBD> <20>¿쿡 '"'<27><> <20>ٿ<EFBFBD><D9BF>ְ<EFBFBD>,
// <20><><EFBFBD>ڿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '"'<27><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
else
{
line += quote;
for (size_t k=0; k<token.size(); k++)
{
if (token[k] == quote) line += quote_escape_string;
else line += token[k];
}
line += quote;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ƴ϶<C6B4><CFB6><EFBFBD> ','<27><> <20><>ū<EFBFBD><C5AB> <20>ڿ<EFBFBD><DABF><EFBFBD> <20>ٿ<EFBFBD><D9BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
if (j != row.size() - 1) { line += seperator; }
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
file << line << std::endl;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20>޸𸮿<DEB8><F0B8AEBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
////////////////////////////////////////////////////////////////////////////////
void cCsvFile::Destroy()
{
for (ROWS::iterator itr(m_Rows.begin()); itr != m_Rows.end(); ++itr)
delete *itr;
m_Rows.clear();
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param index <20>ε<EFBFBD><CEB5><EFBFBD>
/// \return cCsvRow* <20>ش<EFBFBD> <20><>
////////////////////////////////////////////////////////////////////////////////
cCsvRow* cCsvFile::operator [] (size_t index)
{
Assert(index < m_Rows.size());
return m_Rows[index];
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param index <20>ε<EFBFBD><CEB5><EFBFBD>
/// \return const cCsvRow* <20>ش<EFBFBD> <20><>
////////////////////////////////////////////////////////////////////////////////
const cCsvRow* cCsvFile::operator [] (size_t index) const
{
Assert(index < m_Rows.size());
return m_Rows[index];
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
////////////////////////////////////////////////////////////////////////////////
cCsvTable::cCsvTable()
: m_CurRow(-1)
{
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20>Ҹ<EFBFBD><D2B8><EFBFBD>
////////////////////////////////////////////////////////////////////////////////
cCsvTable::~cCsvTable()
{
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> CSV <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>Ѵ<EFBFBD>.
/// \param fileName CSV <20><><EFBFBD><EFBFBD> <20≯<EFBFBD>
/// \param seperator <20>ʵ<EFBFBD> <20>и<EFBFBD><D0B8>ڷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> ','<27>̴<EFBFBD>.
/// \param quote <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> '"'<27>̴<EFBFBD>.
/// \return bool <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ߴٸ<DFB4> true, <20>ƴ϶<C6B4><CFB6><EFBFBD> false
////////////////////////////////////////////////////////////////////////////////
bool cCsvTable::Load(const char* fileName, const char seperator, const char quote)
{
Destroy();
return m_File.Load(fileName, seperator, quote);
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѿ<D1BE><EEB0A3>.
/// \return bool <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѿ <20><><EFBFBD><EFBFBD> true<75><65> <20><>ȯ<EFBFBD>ϰ<EFBFBD>, <20><> <20>̻<EFBFBD>
/// <20>Ѿ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ<EFBFBD> <20><><EFBFBD><EFBFBD><ECBFA1> false<73><65> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
////////////////////////////////////////////////////////////////////////////////
bool cCsvTable::Next()
{
// 20<32><30><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ȣ<><C8A3><EFBFBD>ϸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>÷ΰ<C3B7> <20>Ͼ<CFBE>ٵ<EFBFBD>...<2E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
return ++m_CurRow < (int)m_File.GetRowCount() ? true : false;
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD>ڸ<EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \return size_t <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
////////////////////////////////////////////////////////////////////////////////
size_t cCsvTable::ColCount() const
{
return CurRow()->size();
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> int <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param index <20><> <20>ε<EFBFBD><CEB5><EFBFBD>
/// \return int <20><> <20><>
////////////////////////////////////////////////////////////////////////////////
int cCsvTable::AsInt(size_t index) const
{
const cCsvRow* const row = CurRow();
Assert(row);
Assert(index < row->size());
return row->AsInt(index);
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> double <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param index <20><> <20>ε<EFBFBD><CEB5><EFBFBD>
/// \return double <20><> <20><>
////////////////////////////////////////////////////////////////////////////////
double cCsvTable::AsDouble(size_t index) const
{
const cCsvRow* const row = CurRow();
Assert(row);
Assert(index < row->size());
return row->AsDouble(index);
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> std::string <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param index <20><> <20>ε<EFBFBD><CEB5><EFBFBD>
/// \return const char* <20><> <20><>
////////////////////////////////////////////////////////////////////////////////
const char* cCsvTable::AsStringByIndex(size_t index) const
{
const cCsvRow* const row = CurRow();
Assert(row);
Assert(index < row->size());
return row->AsString(index);
}
////////////////////////////////////////////////////////////////////////////////
/// \brief alias<61><73> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
////////////////////////////////////////////////////////////////////////////////
void cCsvTable::Destroy()
{
m_File.Destroy();
m_Alias.Destroy();
m_CurRow = -1;
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \return const cCsvRow* <20>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD><ECBFA1> <20><> <20><><EFBFBD><EFBFBD>
/// <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><>ȯ<EFBFBD>ϰ<EFBFBD>, <20><> <20>̻<EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><ECBFA1> NULL<4C><4C>
/// <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
////////////////////////////////////////////////////////////////////////////////
const cCsvRow* const cCsvTable::CurRow() const
{
if (m_CurRow < 0)
{
Assert(false && "call Next() first!");
return NULL;
}
else if (m_CurRow >= (int)m_File.GetRowCount())
{
Assert(false && "no more rows!");
return NULL;
}
return m_File[m_CurRow];
}

322
db/src/CsvReader.h Normal file
View File

@ -0,0 +1,322 @@
#ifndef __CSVFILE_H__
#define __CSVFILE_H__
#include <string>
#include <vector>
#if _MSC_VER
#include <hash_map>
#else
#include <map>
#endif
////////////////////////////////////////////////////////////////////////////////
/// \class cCsvAlias
/// \brief CSV <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20>߻<EFBFBD><DFBB>ϴ<EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>̱<EFBFBD> <20><><EFBFBD><EFBFBD>
/// <20><><EFBFBD><EFBFBD> <20><>ü.
///
/// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> 0<><30> <20>÷<EFBFBD><C3B7><EFBFBD> A<><41> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD>, 1<><31> <20>÷<EFBFBD><C3B7><EFBFBD> B<><42> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20>־<EFBFBD><D6BE>µ<EFBFBD>...
///
/// <pre>
/// int a = row.AsInt(0);
/// int b = row.AsInt(1);
/// </pre>
///
/// <20><> <20><><EFBFBD>̿<EFBFBD> C<><43> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>÷<EFBFBD><C3B7><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20>ϵ<EFBFBD><CFB5>ڵ<EFBFBD><DAB5>Ǿ<EFBFBD> <20>ִ<EFBFBD>
/// 1<><31><EFBFBD><EFBFBD> ã<>Ƽ<EFBFBD> <20><><EFBFBD>ľ<EFBFBD> <20>ϴµ<CFB4>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߻<EFBFBD><DFBB>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>۾<EFBFBD><DBBE>̴<EFBFBD>.
///
/// <pre>
/// int a = row.AsInt(0);
/// int c = row.AsInt(1);
/// int b = row.AsInt(2); <-- <20><> <20>κ<EFBFBD><CEBA><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ű<EFBFBD><C5B0><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
/// </pre>
///
/// <20><> <20>κ<EFBFBD><CEBA><EFBFBD> <20><><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD> ó<><C3B3><EFBFBD>ϸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EEB0A1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD>̳<EFBFBD><CCB3><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>
/// <20>ִ<EFBFBD>.
////////////////////////////////////////////////////////////////////////////////
class cCsvAlias
{
private:
#if _MSC_VER
typedef stdext::hash_map<std::string, size_t> NAME2INDEX_MAP;
typedef stdext::hash_map<size_t, std::string> INDEX2NAME_MAP;
#else
typedef std::map<std::string, size_t> NAME2INDEX_MAP;
typedef std::map<size_t, std::string> INDEX2NAME_MAP;
#endif
NAME2INDEX_MAP m_Name2Index; ///< <20><> <20>ε<EFBFBD><CEB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD>
INDEX2NAME_MAP m_Index2Name; ///< <20>߸<EFBFBD><DFB8><EFBFBD> alias<61><73> <20>˻<EFBFBD><CBBB>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>߰<EFBFBD><DFB0><EFBFBD><EFBFBD><EFBFBD> <20><>
public:
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
cCsvAlias() {}
/// \brief <20>Ҹ<EFBFBD><D2B8><EFBFBD>
virtual ~cCsvAlias() {}
public:
/// \brief <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD> <20><>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
void AddAlias(const char* name, size_t index);
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
void Destroy();
/// \brief <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
const char* operator [] (size_t index) const;
/// \brief <20≯<EFBFBD><CCB8><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
size_t operator [] (const char* name) const;
private:
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
cCsvAlias(const cCsvAlias&) {}
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
const cCsvAlias& operator = (const cCsvAlias&) { return *this; }
};
////////////////////////////////////////////////////////////////////////////////
/// \class cCsvRow
/// \brief CSV <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> ĸ<><C4B8>ȭ<EFBFBD><C8AD> Ŭ<><C5AC><EFBFBD><EFBFBD>
///
/// CSV<53><56> <20><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>̴<EFBFBD> <20>ϳ<EFBFBD><CFB3><EFBFBD> <20><><EFBFBD><EFBFBD> ',' <20><><EFBFBD>ڷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>̴<EFBFBD>.
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><> <20>ȿ<EFBFBD> Ư<><C6AF> <20><><EFBFBD>ڷ<EFBFBD> <20><><EFBFBD>̴<EFBFBD> ',' <20><><EFBFBD>ڳ<EFBFBD> '"' <20><><EFBFBD>ڰ<EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD>,
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><20>̻<EFBFBD><CCBB>ϰ<EFBFBD> <20><><EFBFBD>Ѵ<EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><>ȭ<EFBFBD><C8AD> <20><><EFBFBD>̴<EFBFBD>.
///
/// <pre>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>̴<EFBFBD> <20><><EFBFBD><EFBFBD> | <20><><EFBFBD><EFBFBD> CSV <20><><EFBFBD>Ͽ<EFBFBD> <20><><EFBFBD><EFBFBD>ִ<EFBFBD> <20><><EFBFBD><EFBFBD>
/// ---------------------+----------------------------------------------------
/// ItemPrice | ItemPrice
/// Item,Price | "Item,Price"
/// Item"Price | "Item""Price"
/// "ItemPrice" | """ItemPrice"""
/// "Item,Price" | """Item,Price"""
/// Item",Price | "Item"",Price"
/// </pre>
///
/// <20><> <20><><EFBFBD>μ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><> <20>ִ<EFBFBD>.
/// - <20><> <20><><EFBFBD>ο<EFBFBD> ',' <20>Ǵ<EFBFBD> '"' <20><><EFBFBD>ڰ<EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD>, <20><> <20>¿쿡 '"' <20><><EFBFBD>ڰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
/// - <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '"' <20><><EFBFBD>ڴ<EFBFBD> 2<><32><EFBFBD><EFBFBD> ġȯ<C4A1>ȴ<EFBFBD>.
///
/// \sa cCsvFile
////////////////////////////////////////////////////////////////////////////////
class cCsvRow : public std::vector<std::string>
{
public:
/// \brief <20><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
cCsvRow() {}
/// \brief <20>Ҹ<EFBFBD><D2B8><EFBFBD>
~cCsvRow() {}
public:
/// \brief <20>ش<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> int <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
int AsInt(size_t index) const { return atoi(at(index).c_str()); }
/// \brief <20>ش<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> double <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
double AsDouble(size_t index) const { return atof(at(index).c_str()); }
/// \brief <20>ش<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
const char* AsString(size_t index) const { return at(index).c_str(); }
/// \brief <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> int <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
int AsInt(const char* name, const cCsvAlias& alias) const {
return atoi( at(alias[name]).c_str() );
}
/// \brief <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> int <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
double AsDouble(const char* name, const cCsvAlias& alias) const {
return atof( at(alias[name]).c_str() );
}
/// \brief <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
const char* AsString(const char* name, const cCsvAlias& alias) const {
return at(alias[name]).c_str();
}
private:
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
cCsvRow(const cCsvRow&) {}
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
const cCsvRow& operator = (const cCsvRow&) { return *this; }
};
////////////////////////////////////////////////////////////////////////////////
/// \class cCsvFile
/// \brief CSV(Comma Seperated Values) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> read/write<74>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD><EFBFBD>
///
/// <b>sample</b>
/// <pre>
/// cCsvFile file;
///
/// cCsvRow row1, row2, row3;
/// row1.push_back("ItemPrice");
/// row1.push_back("Item,Price");
/// row1.push_back("Item\"Price");
///
/// row2.reserve(3);
/// row2[0] = "\"ItemPrice\"";
/// row2[1] = "\"Item,Price\"";
/// row2[2] = "Item\",Price\"";
///
/// row3 = "\"ItemPrice\"\"Item,Price\"Item\",Price\"";
///
/// file.add(row1);
/// file.add(row2);
/// file.add(row3);
/// file.save("test.csv", false);
/// </pre>
///
/// \todo <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD><EFBFBD><EFBFBD> <20>о<EFBFBD><D0BE><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ƴ϶<C6B4>, <20>޸<EFBFBD><DEB8><EFBFBD> <20>ҽ<EFBFBD><D2BD>κ<EFBFBD><CEBA><EFBFBD> <20>д<EFBFBD> <20>Լ<EFBFBD><D4BC><EFBFBD>
/// <20>־<EFBFBD><D6BE><EFBFBD> <20><> <20><> <20>ϴ<EFBFBD>.
////////////////////////////////////////////////////////////////////////////////
class cCsvFile
{
private:
typedef std::vector<cCsvRow*> ROWS;
ROWS m_Rows; ///< <20><> <20>÷<EFBFBD><C3B7><EFBFBD>
public:
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
cCsvFile() {}
/// \brief <20>Ҹ<EFBFBD><D2B8><EFBFBD>
virtual ~cCsvFile() { Destroy(); }
public:
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> CSV <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>Ѵ<EFBFBD>.
bool Load(const char* fileName, const char seperator=',', const char quote='"');
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CSV <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
bool Save(const char* fileName, bool append=false, char seperator=',', char quote='"') const;
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20>޸𸮿<DEB8><F0B8AEBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
void Destroy();
/// \brief <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
cCsvRow* operator [] (size_t index);
/// \brief <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
const cCsvRow* operator [] (size_t index) const;
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
size_t GetRowCount() const { return m_Rows.size(); }
private:
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
cCsvFile(const cCsvFile&) {}
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
const cCsvFile& operator = (const cCsvFile&) { return *this; }
};
////////////////////////////////////////////////////////////////////////////////
/// \class cCsvTable
/// \brief CSV <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> <20><><EFBFBD>̺<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20>ε<EFBFBD><CEB5>ϴ<EFBFBD> <20><><EFBFBD><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><> Ŭ<><C5AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
/// <20><> <20>۾<EFBFBD><DBBE><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD> <20>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ƿ<EFBFBD><C6BF>Ƽ Ŭ<><C5AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
///
/// CSV <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD>, <20><><EFBFBD>ڸ<EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD><EFBFBD>ؾ<EFBFBD> <20>ϴµ<CFB4>, CSV
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٲ<EFBFBD><D9B2><EFBFBD> <20><><EFBFBD><EFBFBD>, <20><> <20><><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>. <20><> <20>۾<EFBFBD><DBBE><EFBFBD> <20><>
/// <20>Ű<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD>ٰ<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߻<EFBFBD><DFBB>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD>. <20>׷<EFBFBD><D7B7>Ƿ<EFBFBD> <20><><EFBFBD>ڷ<EFBFBD>
/// <20>׼<EFBFBD><D7BC><EFBFBD><EFBFBD>ϱ<CFB1>ٴ<EFBFBD> <20><><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ٰ<EFBFBD> <20><> <20><> <20>ִ<EFBFBD>.
///
/// <b>sample</b>
/// <pre>
/// cCsvTable table;
///
/// table.alias(0, "ItemClass");
/// table.alias(1, "ItemType");
///
/// if (table.load("test.csv"))
/// {
/// while (table.next())
/// {
/// std::string item_class = table.AsString("ItemClass");
/// int item_type = table.AsInt("ItemType");
/// }
/// }
/// </pre>
////////////////////////////////////////////////////////////////////////////////
class cCsvTable
{
public :
cCsvFile m_File; ///< CSV <20><><EFBFBD><EFBFBD> <20><>ü
private:
cCsvAlias m_Alias; ///< <20><><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD> <20><> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>ϱ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ü
int m_CurRow; ///< <20><><EFBFBD><EFBFBD> Ⱦ<><C8BE> <20><><EFBFBD><EFBFBD> <20><> <20><>ȣ
public:
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
cCsvTable();
/// \brief <20>Ҹ<EFBFBD><D2B8><EFBFBD>
virtual ~cCsvTable();
public:
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> CSV <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>Ѵ<EFBFBD>.
bool Load(const char* fileName, const char seperator=',', const char quote='"');
/// \brief <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD> <20><>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
void AddAlias(const char* name, size_t index) { m_Alias.AddAlias(name, index); }
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѿ<D1BE><EEB0A3>.
bool Next();
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD>ڸ<EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
size_t ColCount() const;
/// \brief <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> int <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
int AsInt(size_t index) const;
/// \brief <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> double <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
double AsDouble(size_t index) const;
/// \brief <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> std::string <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
const char* AsStringByIndex(size_t index) const;
/// \brief <20><> <20≯<EFBFBD><CCB8><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> int <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
int AsInt(const char* name) const { return AsInt(m_Alias[name]); }
/// \brief <20><> <20≯<EFBFBD><CCB8><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> double <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
double AsDouble(const char* name) const { return AsDouble(m_Alias[name]); }
/// \brief <20><> <20≯<EFBFBD><CCB8><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> std::string <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
const char* AsString(const char* name) const { return AsStringByIndex(m_Alias[name]); }
/// \brief alias<61><73> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
void Destroy();
private:
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
const cCsvRow* const CurRow() const;
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
cCsvTable(const cCsvTable&) {}
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
const cCsvTable& operator = (const cCsvTable&) { return *this; }
};
#endif //__CSVFILE_H__

188
db/src/DBManager.cpp Normal file
View File

@ -0,0 +1,188 @@
#include "stdafx.h"
#include "DBManager.h"
#include "ClientManager.h"
extern std::string g_stLocale;
CDBManager::CDBManager()
{
Initialize();
}
CDBManager::~CDBManager()
{
Destroy();
}
void CDBManager::Initialize()
{
for (int i = 0; i < SQL_MAX_NUM; ++i)
{
m_mainSQL[i] = NULL;
m_directSQL[i] = NULL;
m_asyncSQL[i] = NULL;
}
}
void CDBManager::Destroy()
{
Clear();
}
void CDBManager::Clear()
{
for (int i = 0; i < SQL_MAX_NUM; ++i)
{
if (m_mainSQL[i])
{
delete m_mainSQL[i];
m_mainSQL[i] = NULL;
}
if (m_directSQL[i])
{
delete m_directSQL[i];
m_directSQL[i] = NULL;
}
if (m_asyncSQL[i])
{
delete m_asyncSQL[i];
m_asyncSQL[i] = NULL;
}
}
Initialize();
}
void CDBManager::Quit()
{
for (int i = 0; i < SQL_MAX_NUM; ++i)
{
if (m_mainSQL[i])
m_mainSQL[i]->Quit();
if (m_asyncSQL[i])
m_asyncSQL[i]->Quit();
if (m_directSQL[i])
m_directSQL[i]->Quit();
}
}
SQLMsg * CDBManager::PopResult()
{
SQLMsg * p;
for (int i = 0; i < SQL_MAX_NUM; ++i)
if (m_mainSQL[i] && m_mainSQL[i]->PopResult(&p))
return p;
return NULL;
}
SQLMsg * CDBManager::PopResult(eSQL_SLOT slot)
{
SQLMsg * p;
if (m_mainSQL[slot] && m_mainSQL[slot]->PopResult(&p))
return p;
return NULL;
}
int CDBManager::Connect(int iSlot, const char * db_address, const int db_port, const char * db_name, const char * user, const char * pwd)
{
if (db_address == NULL || db_name == NULL)
return false;
if (iSlot < 0 || iSlot >= SQL_MAX_NUM)
return false;
sys_log(0, "CREATING DIRECT_SQL");
m_directSQL[iSlot] = new CAsyncSQL2;
if (!m_directSQL[iSlot]->Setup(db_address, user, pwd, db_name, g_stLocale.c_str(), true, db_port))
{
Clear();
return false;
}
sys_log(0, "CREATING MAIN_SQL");
m_mainSQL[iSlot] = new CAsyncSQL2;
if (!m_mainSQL[iSlot]->Setup(db_address, user, pwd, db_name, g_stLocale.c_str(), false, db_port))
{
Clear();
return false;
}
sys_log(0, "CREATING ASYNC_SQL");
m_asyncSQL[iSlot] = new CAsyncSQL2;
if (!m_asyncSQL[iSlot]->Setup(db_address, user, pwd, db_name, g_stLocale.c_str(), false, db_port))
{
Clear();
return false;
}
return true;
}
SQLMsg * CDBManager::DirectQuery(const char * c_pszQuery, int iSlot)
{
return m_directSQL[iSlot]->DirectQuery(c_pszQuery);
}
extern CPacketInfo g_query_info;
extern int g_query_count[2];
void CDBManager::ReturnQuery(const char * c_pszQuery, int iType, IDENT dwIdent, void * udata, int iSlot)
{
assert(iSlot < SQL_MAX_NUM);
//sys_log(0, "ReturnQuery %s", c_pszQuery);
CQueryInfo * p = new CQueryInfo;
p->iType = iType;
p->dwIdent = dwIdent;
p->pvData = udata;
m_mainSQL[iSlot]->ReturnQuery(c_pszQuery, p);
//g_query_info.Add(iType);
++g_query_count[0];
}
void CDBManager::AsyncQuery(const char * c_pszQuery, int iSlot)
{
assert(iSlot < SQL_MAX_NUM);
m_asyncSQL[iSlot]->AsyncQuery(c_pszQuery);
++g_query_count[1];
}
unsigned long CDBManager::EscapeString(void *to, const void *from, unsigned long length, int iSlot)
{
assert(iSlot < SQL_MAX_NUM);
return mysql_real_escape_string(m_directSQL[iSlot]->GetSQLHandle(), (char *) to, (const char *) from, length);
}
void CDBManager::SetLocale(const char * szLocale)
{
const std::string stLocale(szLocale);
sys_log(0, "SetLocale start" );
for (int n = 0; n < SQL_MAX_NUM; ++n)
{
m_mainSQL[n]->SetLocale(stLocale);
m_directSQL[n]->SetLocale(stLocale);
m_asyncSQL[n]->SetLocale(stLocale);
}
sys_log(0, "End setlocale %s", szLocale);
}
void CDBManager::QueryLocaleSet()
{
for (int n = 0; n < SQL_MAX_NUM; ++n)
{
m_mainSQL[n]->QueryLocaleSet();
m_directSQL[n]->QueryLocaleSet();
m_asyncSQL[n]->QueryLocaleSet();
}
}

100
db/src/DBManager.h Normal file
View File

@ -0,0 +1,100 @@
// vim:ts=8 sw=4
#ifndef __INC_METIN2_DB_DBMANAGER_H__
#define __INC_METIN2_DB_DBMANAGER_H__
// <20><><EFBFBD><EFBFBD> Ŀ<>ؼ<EFBFBD> Ŭ<><C5AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>... <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>޾ƿ<DEBE><C6BF><EFBFBD>
// <20><><EFBFBD><EFBFBD> <20>ϵ<EFBFBD><CFB5><EFBFBD> ó<><C3B3><EFBFBD>Ѵ<EFBFBD>.
// <20>ڵ<EFBFBD> by <20><><EFBFBD><EFBFBD> <20>ķα׷<CEB1><D7B7><EFBFBD> <20>Ƴ<EFBFBD><C6B3><EFBFBD>~ = _=)b
#include <mysql/mysql.h>
#include "../../libsql/AsyncSQL.h"
#define SQL_SAFE_LENGTH(size) (size * 2 + 1)
#define QUERY_SAFE_LENGTH(size) (1024 + SQL_SAFE_LENGTH(size))
class CQueryInfo
{
public:
int iType;
DWORD dwIdent;
void * pvData;
};
enum eSQL_SLOT
{
SQL_PLAYER,
SQL_ACCOUNT,
SQL_COMMON,
SQL_HOTBACKUP,
SQL_MAX_NUM,
};
class CDBManager : public singleton<CDBManager>
{
protected:
void Initialize();
void Destroy();
public:
CDBManager();
virtual ~CDBManager();
void Clear();
void Quit();
int Connect(int iSlot, const char * host, int port, const char* dbname, const char* user, const char* pass);
void ReturnQuery(const char * c_pszQuery, int iType, DWORD dwIdent, void * pvData, int iSlot = SQL_PLAYER);
void AsyncQuery(const char * c_pszQuery, int iSlot = SQL_PLAYER);
SQLMsg * DirectQuery(const char * c_pszQuery, int iSlot = SQL_PLAYER);
SQLMsg * PopResult();
SQLMsg * PopResult(eSQL_SLOT slot );
unsigned long EscapeString(void * to, const void * from, unsigned long length, int iSlot = SQL_PLAYER);
DWORD CountReturnQuery(int i) { return m_mainSQL[i] ? m_mainSQL[i]->CountQuery() : 0; }
DWORD CountReturnResult(int i) { return m_mainSQL[i] ? m_mainSQL[i]->CountResult() : 0; }
DWORD CountReturnQueryFinished(int i) { return m_mainSQL[i] ? m_mainSQL[i]->CountQueryFinished() : 0; }
DWORD CountReturnCopiedQuery(int i) { return m_mainSQL[i] ? m_mainSQL[i]->GetCopiedQueryCount() : 0; }
DWORD CountAsyncQuery(int i) { return m_asyncSQL[i] ? m_asyncSQL[i]->CountQuery() : 0; }
DWORD CountAsyncResult(int i) { return m_asyncSQL[i] ? m_asyncSQL[i]->CountResult() : 0; }
DWORD CountAsyncQueryFinished(int i) { return m_asyncSQL[i] ? m_asyncSQL[i]->CountQueryFinished() : 0; }
DWORD CountAsyncCopiedQuery(int i) { return m_asyncSQL[i] ? m_asyncSQL[i]->GetCopiedQueryCount() : 0; }
void ResetCounter()
{
for (int i = 0; i < SQL_MAX_NUM; ++i)
{
if (m_mainSQL[i])
{
m_mainSQL[i]->ResetQueryFinished();
m_mainSQL[i]->ResetCopiedQueryCount();
}
if (m_asyncSQL[i])
{
m_asyncSQL[i]->ResetQueryFinished();
m_asyncSQL[i]->ResetCopiedQueryCount();
}
}
}
private:
CAsyncSQL2 * m_mainSQL[SQL_MAX_NUM];
CAsyncSQL2 * m_directSQL[SQL_MAX_NUM];
CAsyncSQL2 * m_asyncSQL[SQL_MAX_NUM];
int m_quit; // looping flag
//CHARSET
public:
void SetLocale(const char * szLocale );
void QueryLocaleSet();
private:
//END_CHARSET
};
#endif

1491
db/src/GuildManager.cpp Normal file

File diff suppressed because it is too large Load Diff

260
db/src/GuildManager.h Normal file
View File

@ -0,0 +1,260 @@
// vim:ts=8 sw=4
#ifndef __INC_GUILD_MANAGER_H
#define __INC_GUILD_MANAGER_H
#include "Peer.h"
#include <queue>
#include <utility>
#include "../../libsql/libsql.h"
#include "../../libpoly/Poly.h"
enum
{
GUILD_WARP_WAR_CHANNEL = 99
};
class CGuildWarReserve;
struct TGuildDeclareInfo
{
BYTE bType;
DWORD dwGuildID[2];
TGuildDeclareInfo(BYTE _bType, DWORD _dwGuildID1, DWORD _dwGuildID2)
: bType(_bType)
{
dwGuildID[0] = _dwGuildID1;
dwGuildID[1] = _dwGuildID2;
}
bool operator < (const TGuildDeclareInfo& r) const
{
return dwGuildID[0] < r.dwGuildID[0] || dwGuildID[0] == r.dwGuildID[0] && dwGuildID[1] < r.dwGuildID[1];
}
TGuildDeclareInfo& operator = (const TGuildDeclareInfo& r)
{
bType = r.bType;
dwGuildID[0] = r.dwGuildID[0];
dwGuildID[1] = r.dwGuildID[1];
return *this;
}
};
struct TGuildWaitStartInfo
{
BYTE bType;
DWORD GID[2];
long lWarPrice;
long lInitialScore;
CGuildWarReserve * pkReserve;
TGuildWaitStartInfo(BYTE _bType,
DWORD _g1,
DWORD _g2,
long _lWarPrice,
long _lInitialScore,
CGuildWarReserve * _pkReserve)
: bType(_bType), lWarPrice(_lWarPrice), lInitialScore(_lInitialScore), pkReserve(_pkReserve)
{
GID[0] = _g1;
GID[1] = _g2;
}
bool operator < (const TGuildWaitStartInfo& r) const
{
return GID[0] < r.GID[0] || GID[0] == r.GID[0] && GID[1] < r.GID[1];
}
};
struct TGuildWarPQElement
{
bool bEnd;
BYTE bType;
DWORD GID[2];
DWORD iScore[2];
DWORD iBetScore[2];
TGuildWarPQElement(BYTE _bType, DWORD GID1, DWORD GID2) : bEnd(false), bType(_bType)
{
bType = _bType;
GID[0] = GID1;
GID[1] = GID2;
iScore[0] = iScore[1] = 0;
iBetScore[0] = iBetScore[1] = 0;
}
};
struct TGuildSkillUsed
{
DWORD GID;
DWORD dwSkillVnum;
// GUILD_SKILL_COOLTIME_BUG_FIX
TGuildSkillUsed(DWORD _GID, DWORD _dwSkillVnum) : GID(_GID), dwSkillVnum(_dwSkillVnum)
{
}
// END_OF_GUILD_SKILL_COOLTIME_BUG_FIX
};
inline bool operator < (const TGuildSkillUsed& a, const TGuildSkillUsed& b)
{
return a.GID < b.GID || a.GID == b.GID && a.dwSkillVnum < b.dwSkillVnum;
}
typedef struct SGuild
{
SGuild() : ladder_point(0), win(0), draw(0), loss(0), gold(0), level(0)
{
memset(szName, 0, sizeof(szName));
}
char szName[GUILD_NAME_MAX_LEN+1];
int ladder_point;
int win;
int draw;
int loss;
int gold;
int level;
} TGuild;
typedef struct SGuildWarInfo
{
time_t tEndTime;
TGuildWarPQElement * pElement;
CGuildWarReserve * pkReserve;
SGuildWarInfo() : pElement(NULL)
{
}
} TGuildWarInfo;
class CGuildWarReserve
{
public:
CGuildWarReserve(const TGuildWarReserve& rTable);
void Initialize();
TGuildWarReserve & GetDataRef()
{
return m_data;
}
void OnSetup(CPeer * peer);
bool Bet(const char * pszLogin, DWORD dwGold, DWORD dwGuild);
void Draw();
void End(int iScoreFrom, int iScoreTo);
int GetLastNoticeMin() { return m_iLastNoticeMin; }
void SetLastNoticeMin(int iMin) { m_iLastNoticeMin = iMin; }
private:
CGuildWarReserve(); // <20><20><><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD> <20>ǵ<EFBFBD><C7B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
TGuildWarReserve m_data;
// <login, <guild, gold>>
std::map<std::string, std::pair<DWORD, DWORD> > mapBet;
int m_iLastNoticeMin;
};
class CGuildManager : public singleton<CGuildManager>
{
public:
CGuildManager();
virtual ~CGuildManager();
void Initialize();
void Load(DWORD dwGuildID);
TGuild & TouchGuild(DWORD GID);
void Update();
void OnSetup(CPeer * peer);
void StartWar(BYTE bType, DWORD GID1, DWORD GID2, CGuildWarReserve * pkReserve = NULL);
void UpdateScore(DWORD guild_gain_point, DWORD guild_opponent, int iScore, int iBetScore);
void AddDeclare(BYTE bType, DWORD guild_from, DWORD guild_to);
void RemoveDeclare(DWORD guild_from, DWORD guild_to);
bool TakeBetPrice(DWORD dwGuildTo, DWORD dwGuildFrom, long lWarPrice);
bool WaitStart(TPacketGuildWar * p);
void RecvWarEnd(DWORD GID1, DWORD GID2);
void RecvWarOver(DWORD dwGuildWinner, DWORD dwGuildLoser, bool bDraw, long lWarPrice);
void ChangeLadderPoint(DWORD GID, int change);
void UseSkill(DWORD dwGuild, DWORD dwSkillVnum, DWORD dwCooltime);
INT GetGuildGold(DWORD dwGuild);
void DepositMoney(DWORD dwGuild, INT lGold);
void WithdrawMoney(CPeer* peer, DWORD dwGuild, INT lGold);
void WithdrawMoneyReply(DWORD dwGuild, BYTE bGiveSuccess, INT lGold);
void MoneyChange(DWORD dwGuild, DWORD dwGold);
void QueryRanking();
void ResultRanking(MYSQL_RES * pRes);
int GetRanking(DWORD dwGID);
//
// Reserve War
//
void BootReserveWar();
bool ReserveWar(TPacketGuildWar * p);
void ProcessReserveWar();
bool Bet(DWORD dwID, const char * c_pszLogin, DWORD dwGold, DWORD dwGuild);
void CancelWar(DWORD GID1, DWORD GID2);
bool ChangeMaster(DWORD dwGID, DWORD dwFrom, DWORD dwTo);
private:
void ParseResult(SQLResult * pRes);
void RemoveWar(DWORD GID1, DWORD GID2); // erase war from m_WarMap and set end on priority queue
void WarEnd(DWORD GID1, DWORD GID2, bool bDraw = false);
int GetLadderPoint(DWORD GID);
void GuildWarWin(DWORD GID);
void GuildWarDraw(DWORD GID);
void GuildWarLose(DWORD GID);
void ProcessDraw(DWORD dwGuildID1, DWORD dwGuildID2);
void ProcessWinLose(DWORD dwGuildWinner, DWORD dwGuildLoser);
bool IsHalfWinLadderPoint(DWORD dwGuildWinner, DWORD dwGuildLoser);
std::map<DWORD, TGuild> m_map_kGuild;
std::map<DWORD, std::map<DWORD, time_t> > m_mapGuildWarEndTime;
std::set<TGuildDeclareInfo> m_DeclareMap; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>¸<EFBFBD> <20><><EFBFBD><EFBFBD>
std::map<DWORD, std::map<DWORD, TGuildWarInfo> > m_WarMap;
typedef std::pair<time_t, TGuildWarPQElement *> stPairGuildWar;
typedef std::pair<time_t, TGuildSkillUsed> stPairSkillUsed;
typedef std::pair<time_t, TGuildWaitStartInfo> stPairWaitStart;
std::priority_queue<stPairGuildWar, std::vector<stPairGuildWar>, std::greater<stPairGuildWar> >
m_pqOnWar;
std::priority_queue<stPairWaitStart, std::vector<stPairWaitStart>, std::greater<stPairWaitStart> >
m_pqWaitStart;
std::priority_queue<stPairSkillUsed, std::vector<stPairSkillUsed>, std::greater<stPairSkillUsed> >
m_pqSkill;
std::map<DWORD, CGuildWarReserve *> m_map_kWarReserve;
CPoly polyPower;
CPoly polyHandicap;
// GID Ranking
std::map<DWORD, int> map_kLadderPointRankingByGID;
};
#endif

86
db/src/HB.cpp Normal file
View File

@ -0,0 +1,86 @@
#include "stdafx.h"
#include "HB.h"
#include "Main.h"
#include "DBManager.h"
#include <memory>
PlayerHB::PlayerHB()
{
m_iExpireTime = 3600; // 1 hour hotbackup default.
}
PlayerHB::~PlayerHB()
{
}
bool PlayerHB::Initialize()
{
char szQuery[128];
snprintf(szQuery, sizeof(szQuery), "SHOW CREATE TABLE player%s", GetTablePostfix());
std::auto_ptr<SQLMsg> pMsg(CDBManager::instance().DirectQuery(szQuery));
if (pMsg->Get()->uiNumRows == 0)
return false;
MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
m_stCreateTableQuery = row[1];
return true;
}
//
// @version 05/07/05 Bang2ni - id <20><> <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> data <20><> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> data <20><> insert <20>ϴ<EFBFBD><CFB4>ڵ<EFBFBD> <20>߰<EFBFBD>.
//
void PlayerHB::Put(DWORD id)
{
itertype(m_map_data) it = m_map_data.find(id);
if (it == m_map_data.end())
{
Query(id);
m_map_data.insert(std::pair< DWORD, time_t >(id, get_dword_time()));
return;
}
if (time(0) - it->second > m_iExpireTime)
Query(id);
}
//
// @version 05/07/05 Bang2ni - Query string <20><><EFBFBD>۰<EFBFBD> <20>۾Ƽ<DBBE> <20>÷<EFBFBD><C3B7><EFBFBD>.
//
bool PlayerHB::Query(DWORD id)
{
time_t ct = time(0);
struct tm curr_tm = *localtime(&ct);
char szTableName[64];
snprintf(szTableName, sizeof(szTableName), "hb_%02d%02d%02d%02d_player%s",
curr_tm.tm_year - 100, curr_tm.tm_mon + 1, curr_tm.tm_mday, curr_tm.tm_hour, GetTablePostfix());
char szQuery[4096];
if (m_stTableName.compare(szTableName))
{
char szFind[32];
snprintf(szFind, sizeof(szFind), "CREATE TABLE `player%s`", GetTablePostfix());
int pos = m_stCreateTableQuery.find(szFind);
if (pos < 0)
{
sys_err("cannot find %s ", szFind);
// sys_err("cannot find %s in %s", szFind, m_stCreateTableQuery.c_str());
return false;
}
snprintf(szQuery, sizeof(szQuery), "CREATE TABLE IF NOT EXISTS %s%s", szTableName, m_stCreateTableQuery.c_str() + strlen(szFind));
// sys_log(0, "%s", szQuery);
std::auto_ptr<SQLMsg> pMsg(CDBManager::instance().DirectQuery(szQuery, SQL_HOTBACKUP));
m_stTableName = szTableName;
}
snprintf(szQuery, sizeof(szQuery), "REPLACE INTO %s SELECT * FROM %splayer%s WHERE id=%u", m_stTableName.c_str(), GetPlayerDBName(), GetTablePostfix(), id);
CDBManager::instance().AsyncQuery(szQuery, SQL_HOTBACKUP);
return true;
}

24
db/src/HB.h Normal file
View File

@ -0,0 +1,24 @@
// vim:ts=8 sw=4
#ifndef __INC_METIN_II_PLAYERHB_H__
#define __INC_METIN_II_PLAYERHB_H__
class PlayerHB : public singleton<PlayerHB>
{
public:
PlayerHB();
virtual ~PlayerHB();
bool Initialize();
void Put(DWORD id);
private:
bool Query(DWORD id);
std::map<DWORD, time_t> m_map_data;
std::string m_stCreateTableQuery;
std::string m_stTableName;
int m_iExpireTime;
};
#endif

129
db/src/ItemAwardManager.cpp Normal file
View File

@ -0,0 +1,129 @@
#include "stdafx.h"
#include "QID.h"
#include "DBManager.h"
#include "ItemAwardManager.h"
#include "Peer.h"
#include "ClientManager.h"
DWORD g_dwLastCachedItemAwardID = 0;
ItemAwardManager::ItemAwardManager()
{
}
ItemAwardManager::~ItemAwardManager()
{
}
void ItemAwardManager::RequestLoad()
{
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery), "SELECT id,login,vnum,count,socket0,socket1,socket2,mall,why FROM item_award WHERE taken_time IS NULL and id > %d", g_dwLastCachedItemAwardID);
CDBManager::instance().ReturnQuery(szQuery, QID_ITEM_AWARD_LOAD, 0, NULL);
}
void ItemAwardManager::Load(SQLMsg * pMsg)
{
MYSQL_RES * pRes = pMsg->Get()->pSQLResult;
for (uint i = 0; i < pMsg->Get()->uiNumRows; ++i)
{
MYSQL_ROW row = mysql_fetch_row(pRes);
int col = 0;
DWORD dwID = 0;
str_to_number(dwID, row[col++]);
if (m_map_award.find(dwID) != m_map_award.end())
continue;
TItemAward * kData = new TItemAward;
memset(kData, 0, sizeof(TItemAward));
kData->dwID = dwID;
trim_and_lower(row[col++], kData->szLogin, sizeof(kData->szLogin));
str_to_number(kData->dwVnum, row[col++]);
str_to_number(kData->dwCount, row[col++]);
str_to_number(kData->dwSocket0, row[col++]);
str_to_number(kData->dwSocket1, row[col++]);
str_to_number(kData->dwSocket2, row[col++]);
str_to_number(kData->bMall, row[col++]);
if (row[col])
{
strlcpy(kData->szWhy, row[col], sizeof(kData->szWhy));
//<2F><><EFBFBD><EFBFBD> <20>߿<EFBFBD> why<68>ݷ뿡 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
char* whyStr = kData->szWhy; //why <20>ݷ<EFBFBD> <20>б<EFBFBD>
char cmdStr[100] = ""; //why<68>ݷ뿡<DDB7><EBBFA1> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ӽ<EFBFBD> <20><><EFBFBD>ڿ<EFBFBD><DABF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ص<EFBFBD>
strcpy(cmdStr,whyStr); //<2F><><EFBFBD>ɾ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ū<EFBFBD><C5AB><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ūȭ <20>DZ<EFBFBD> <20><><EFBFBD><EFBFBD>
char command[20] = "";
strcpy(command,CClientManager::instance().GetCommand(cmdStr)); // command <20><><EFBFBD><EFBFBD>
//sys_err("%d, %s",pItemAward->dwID,command);
if( !(strcmp(command,"GIFT") )) // command <20><> GIFT<46≯<EFBFBD>
{
TPacketItemAwardInfromer giftData;
strcpy(giftData.login, kData->szLogin); //<2F>α<EFBFBD><CEB1><EFBFBD> <20><><EFBFBD>̵<EFBFBD> <20><><EFBFBD><EFBFBD>
strcpy(giftData.command, command); //<2F><><EFBFBD>ɾ<EFBFBD> <20><><EFBFBD><EFBFBD>
giftData.vnum = kData->dwVnum; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> vnum<75><6D> <20><><EFBFBD><EFBFBD>
CClientManager::instance().ForwardPacket(HEADER_DG_ITEMAWARD_INFORMER,&giftData,sizeof(TPacketItemAwardInfromer));
}
}
m_map_award.insert(std::make_pair(dwID, kData));
printf("ITEM_AWARD load id %u bMall %d \n", kData->dwID, kData->bMall);
sys_log(0, "ITEM_AWARD: load id %lu login %s vnum %lu count %u socket %lu", kData->dwID, kData->szLogin, kData->dwVnum, kData->dwCount, kData->dwSocket0);
std::set<TItemAward *> & kSet = m_map_kSetAwardByLogin[kData->szLogin];
kSet.insert(kData);
if (dwID > g_dwLastCachedItemAwardID)
g_dwLastCachedItemAwardID = dwID;
}
}
std::set<TItemAward *> * ItemAwardManager::GetByLogin(const char * c_pszLogin)
{
itertype(m_map_kSetAwardByLogin) it = m_map_kSetAwardByLogin.find(c_pszLogin);
if (it == m_map_kSetAwardByLogin.end())
return NULL;
return &it->second;
}
void ItemAwardManager::Taken(DWORD dwAwardID, DWORD dwItemID)
{
itertype(m_map_award) it = m_map_award.find(dwAwardID);
if (it == m_map_award.end())
{
sys_log(0, "ITEM_AWARD: Taken ID not exist %lu", dwAwardID);
return;
}
TItemAward * k = it->second;
k->bTaken = true;
//
// Update taken_time in database to prevent not to give him again.
//
char szQuery[QUERY_MAX_LEN];
snprintf(szQuery, sizeof(szQuery),
"UPDATE item_award SET taken_time=NOW(),item_id=%u WHERE id=%u AND taken_time IS NULL",
dwItemID, dwAwardID);
CDBManager::instance().ReturnQuery(szQuery, QID_ITEM_AWARD_TAKEN, 0, NULL);
}
std::map<DWORD, TItemAward *>& ItemAwardManager::GetMapAward()
{
return m_map_award;
}
std::map<std::string, std::set<TItemAward *> >& ItemAwardManager::GetMapkSetAwardByLogin()
{
return m_map_kSetAwardByLogin;
}

43
db/src/ItemAwardManager.h Normal file
View File

@ -0,0 +1,43 @@
// vim:ts=8 sw=4
#ifndef __INC_ITEM_AWARD_H
#define __INC_ITEM_AWARD_H
#include <map>
#include <set>
#include "Peer.h"
typedef struct SItemAward
{
DWORD dwID;
char szLogin[LOGIN_MAX_LEN+1];
DWORD dwVnum;
DWORD dwCount;
DWORD dwSocket0;
DWORD dwSocket1;
DWORD dwSocket2;
char szWhy[ITEM_AWARD_WHY_MAX_LEN+1];
bool bTaken;
bool bMall;
} TItemAward;
class ItemAwardManager : public singleton<ItemAwardManager>
{
public:
ItemAwardManager();
virtual ~ItemAwardManager();
void RequestLoad();
void Load(SQLMsg * pMsg);
std::set<TItemAward *> * GetByLogin(const char * c_pszLogin);
void Taken(DWORD dwAwardID, DWORD dwItemID);
// gift notify
std::map<DWORD, TItemAward *>& GetMapAward();
std::map<std::string, std::set<TItemAward *> >& GetMapkSetAwardByLogin();
private:
// ID, ItemAward pair
std::map<DWORD, TItemAward *> m_map_award;
// PID, ItemAward pair
std::map<std::string, std::set<TItemAward *> > m_map_kSetAwardByLogin;
};
#endif

View File

@ -0,0 +1,165 @@
#include "stdafx.h"
#include "ItemIDRangeManager.h"
#include "Main.h"
#include "DBManager.h"
#include "ClientManager.h"
#include "Peer.h"
CItemIDRangeManager::CItemIDRangeManager()
{
m_listData.clear();
}
void CItemIDRangeManager::Build()
{
DWORD dwMin = 0;
DWORD dwMax = 0;
TItemIDRangeTable range;
for (int i = 0; ; ++i)
{
dwMin = cs_dwMinimumRange * (i + 1) + 1;
dwMax = cs_dwMinimumRange * (i + 2);
if (dwMax == cs_dwMaxItemID)
break;
if (CClientManager::instance().GetItemRange().dwMin <= dwMin &&
CClientManager::instance().GetItemRange().dwMax >= dwMax)
{
continue;
}
if (BuildRange(dwMin, dwMax, range) == true)
{
m_listData.push_back(range);
}
}
}
struct FCheckCollision
{
bool hasCollision;
TItemIDRangeTable range;
FCheckCollision(TItemIDRangeTable data)
{
hasCollision = false;
range = data;
}
void operator() (CPeer* peer)
{
if (hasCollision == false)
{
hasCollision = peer->CheckItemIDRangeCollision(range);
}
}
};
TItemIDRangeTable CItemIDRangeManager::GetRange()
{
TItemIDRangeTable ret;
ret.dwMin = 0;
ret.dwMax = 0;
ret.dwUsableItemIDMin = 0;
if (m_listData.size() > 0)
{
while (m_listData.size() > 0)
{
ret = m_listData.front();
m_listData.pop_front();
FCheckCollision f(ret);
CClientManager::instance().for_each_peer(f);
if (f.hasCollision == false) return ret;
}
}
for (int i = 0; i < 10; ++i)
sys_err("ItemIDRange: NO MORE ITEM ID RANGE");
return ret;
}
bool CItemIDRangeManager::BuildRange(DWORD dwMin, DWORD dwMax, TItemIDRangeTable& range)
{
char szQuery[1024];
DWORD dwItemMaxID = 0;
SQLMsg* pMsg = NULL;
MYSQL_ROW row;
snprintf(szQuery, sizeof(szQuery), "SELECT MAX(id) FROM item%s WHERE id >= %u and id <= %u", GetTablePostfix(), dwMin, dwMax);
pMsg = CDBManager::instance().DirectQuery(szQuery);
if (pMsg != NULL)
{
if (pMsg->Get()->uiNumRows > 0)
{
row = mysql_fetch_row(pMsg->Get()->pSQLResult);
str_to_number(dwItemMaxID, row[0]);
}
delete pMsg;
}
if (dwItemMaxID == 0)
dwItemMaxID = dwMin;
else
dwItemMaxID++;
if ((dwMax < dwItemMaxID) || (dwMax - dwItemMaxID < cs_dwMinimumRemainCount))
{
sys_log(0, "ItemIDRange: Build %u ~ %u start: %u\tNOT USE remain count is below %u",
dwMin, dwMax, dwItemMaxID, cs_dwMinimumRemainCount);
}
else
{
range.dwMin = dwMin;
range.dwMax = dwMax;
range.dwUsableItemIDMin = dwItemMaxID;
snprintf(szQuery, sizeof(szQuery), "SELECT COUNT(*) FROM item%s WHERE id >= %u AND id <= %u",
GetTablePostfix(), range.dwUsableItemIDMin, range.dwMax);
pMsg = CDBManager::instance().DirectQuery(szQuery);
if (pMsg != NULL)
{
if (pMsg->Get()->uiNumRows > 0)
{
DWORD count = 0;
row = mysql_fetch_row(pMsg->Get()->pSQLResult);
str_to_number(count, row[0]);
if (count > 0)
{
sys_err("ItemIDRange: Build: %u ~ %u\thave a item", range.dwUsableItemIDMin, range.dwMax);
return false;
}
else
{
sys_log(0, "ItemIDRange: Build: %u ~ %u start:%u", range.dwMin, range.dwMax, range.dwUsableItemIDMin);
return true;
}
}
delete pMsg;
}
}
return false;
}
void CItemIDRangeManager::UpdateRange(DWORD dwMin, DWORD dwMax)
{
TItemIDRangeTable range;
if (BuildRange(dwMin, dwMax, range) == true)
{
m_listData.push_back(range);
}
}

View File

@ -0,0 +1,24 @@
// vim:ts=4 sw=4
#ifndef __INC_METIN_II_ITEM_ID_RANGE_MANAGER_H__
#define __INC_METIN_II_ITEM_ID_RANGE_MANAGER_H__
class CItemIDRangeManager : public singleton<CItemIDRangeManager>
{
private :
const static DWORD cs_dwMaxItemID = 4290000000UL;
const static DWORD cs_dwMinimumRange = 10000000UL;
const static DWORD cs_dwMinimumRemainCount = 10000UL;
std::list<TItemIDRangeTable> m_listData;
public :
CItemIDRangeManager();
void Build();
bool BuildRange(DWORD dwMin, DWORD dwMax, TItemIDRangeTable& range);
void UpdateRange(DWORD dwMin, DWORD dwMax);
TItemIDRangeTable GetRange();
};
#endif

60
db/src/Lock.cpp Normal file
View File

@ -0,0 +1,60 @@
#include "stdafx.h"
#include "Lock.h"
CLock::CLock()
{
}
CLock::~CLock()
{
}
void CLock::Initialize()
{
m_bLocked = false;
#ifndef __WIN32__
pthread_mutex_init(&m_lock, NULL);
#else
::InitializeCriticalSection(&m_lock);
#endif
}
void CLock::Destroy()
{
assert(!m_bLocked && "lock didn't released");
#ifndef __WIN32__
pthread_mutex_destroy(&m_lock);
#else
::DeleteCriticalSection(&m_lock);
#endif
}
int CLock::Trylock()
{
#ifndef __WIN32__
return pthread_mutex_trylock(&m_lock);
#else
return ::TryEnterCriticalSection(&m_lock);
#endif
}
void CLock::Lock()
{
#ifndef __WIN32__
pthread_mutex_lock(&m_lock);
#else
::EnterCriticalSection(&m_lock);
#endif
m_bLocked = true;
}
void CLock::Unlock()
{
assert(m_bLocked && "lock didn't issued");
m_bLocked = false;
#ifndef __WIN32__
pthread_mutex_unlock(&m_lock);
#else
::LeaveCriticalSection(&m_lock);
#endif
}

27
db/src/Lock.h Normal file
View File

@ -0,0 +1,27 @@
// vim:ts=8 sw=4
#ifndef __INC_LOCK_H__
#define __INC_LOCK_H__
#ifdef __WIN32__
typedef CRITICAL_SECTION lock_t;
#else
typedef pthread_mutex_t lock_t;
#endif
class CLock
{
public:
CLock();
~CLock();
void Initialize();
void Destroy();
int Trylock();
void Lock();
void Unlock();
private:
lock_t m_lock;
bool m_bLocked;
};
#endif

123
db/src/LoginData.cpp Normal file
View File

@ -0,0 +1,123 @@
#include "stdafx.h"
#include "LoginData.h"
#include "ClientManager.h"
CLoginData::CLoginData()
{
m_dwKey = 0;
memset(m_adwClientKey, 0, sizeof(m_adwClientKey));
m_dwConnectedPeerHandle = 0;
m_dwLogonTime = 0;
memset(m_szIP, 0, sizeof(m_szIP));
m_bPlay = false;
m_bDeleted = false;
m_bBillType = 0;
m_dwBillID = 0;
m_lastPlayTime = 0;
m_dwLastPlayerID = 0;
memset(&m_data, 0, sizeof(TAccountTable));
}
TAccountTable & CLoginData::GetAccountRef()
{
return m_data;
}
void CLoginData::SetClientKey(const DWORD * c_pdwClientKey)
{
thecore_memcpy(&m_adwClientKey, c_pdwClientKey, sizeof(DWORD) * 4);
}
const DWORD * CLoginData::GetClientKey()
{
return &m_adwClientKey[0];
}
void CLoginData::SetKey(DWORD dwKey)
{
m_dwKey = dwKey;
}
DWORD CLoginData::GetKey()
{
return m_dwKey;
}
void CLoginData::SetConnectedPeerHandle(DWORD dwHandle)
{
m_dwConnectedPeerHandle = dwHandle;
}
DWORD CLoginData::GetConnectedPeerHandle()
{
return m_dwConnectedPeerHandle;
}
void CLoginData::SetLogonTime()
{
m_dwLogonTime = get_dword_time();
}
DWORD CLoginData::GetLogonTime()
{
return m_dwLogonTime;
}
void CLoginData::SetIP(const char * c_pszIP)
{
strlcpy(m_szIP, c_pszIP, sizeof(m_szIP));
}
const char * CLoginData::GetIP()
{
return m_szIP;
}
void CLoginData::SetPlay(bool bOn)
{
if (bOn)
{
sys_log(0, "SetPlay on %lu %s", GetKey(), m_data.login);
SetLogonTime();
}
else
sys_log(0, "SetPlay off %lu %s", GetKey(), m_data.login);
m_bPlay = bOn;
m_lastPlayTime = CClientManager::instance().GetCurrentTime();
}
bool CLoginData::IsPlay()
{
return m_bPlay;
}
void CLoginData::SetDeleted(bool bSet)
{
m_bDeleted = bSet;
}
bool CLoginData::IsDeleted()
{
return m_bDeleted;
}
void CLoginData::SetPremium(int * paiPremiumTimes)
{
thecore_memcpy(m_aiPremiumTimes, paiPremiumTimes, sizeof(m_aiPremiumTimes));
}
int CLoginData::GetPremium(BYTE type)
{
if (type >= PREMIUM_MAX_NUM)
return 0;
return m_aiPremiumTimes[type];
}
int * CLoginData::GetPremiumPtr()
{
return &m_aiPremiumTimes[0];
}

66
db/src/LoginData.h Normal file
View File

@ -0,0 +1,66 @@
// vim:ts=8 sw=4
#ifndef __INC_METIN_II_DB_LOGINDATA_H__
#define __INC_METIN_II_DB_LOGINDATA_H__
class CLoginData
{
public:
CLoginData();
TAccountTable & GetAccountRef();
void SetClientKey(const DWORD * c_pdwClientKey);
const DWORD * GetClientKey();
void SetKey(DWORD dwKey);
DWORD GetKey();
void SetConnectedPeerHandle(DWORD dwHandle);
DWORD GetConnectedPeerHandle();
void SetLogonTime();
DWORD GetLogonTime();
void SetIP(const char * c_pszIP);
const char * GetIP();
void SetPlay(bool bOn);
bool IsPlay();
void SetDeleted(bool bSet);
bool IsDeleted();
void SetBillID(DWORD id) { m_dwBillID = id; }
DWORD GetBillID() { return m_dwBillID; }
void SetBillType(BYTE type) { m_bBillType = type; }
BYTE GetBillType() { return m_bBillType; }
time_t GetLastPlayTime() { return m_lastPlayTime; }
void SetPremium(int * paiPremiumTimes);
int GetPremium(BYTE type);
int * GetPremiumPtr();
DWORD GetLastPlayerID() const { return m_dwLastPlayerID; }
void SetLastPlayerID(DWORD id) { m_dwLastPlayerID = id; }
private:
DWORD m_dwKey;
DWORD m_adwClientKey[4];
DWORD m_dwConnectedPeerHandle;
DWORD m_dwLogonTime;
char m_szIP[MAX_HOST_LENGTH+1];
bool m_bPlay;
bool m_bDeleted;
BYTE m_bBillType;
DWORD m_dwBillID;
time_t m_lastPlayTime;
int m_aiPremiumTimes[PREMIUM_MAX_NUM];
DWORD m_dwLastPlayerID;
TAccountTable m_data;
};
#endif

430
db/src/Main.cpp Normal file
View File

@ -0,0 +1,430 @@
#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;
//<2F><><EFBFBD><EFBFBD> <20><>
int g_iPlayerCacheFlushSeconds = 60*7;
int g_iItemCacheFlushSeconds = 60*5;
//g_iLogoutSeconds <20><>ġ<EFBFBD><C4A1> g_iPlayerCacheFlushSeconds <20><> g_iItemCacheFlushSeconds <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
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<>ʿ<EFBFBD> <20>ѹ<EFBFBD>
{
}
}
//
// @version 05/06/13 Bang2ni - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ij<><C4B3> flush timeout <20><><EFBFBD><EFBFBD> <20>߰<EFBFBD>.
//
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();
}

9
db/src/Main.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef __INC_MAIN_H__
#define __INC_MAIN_H__
int Start();
void End();
const char * GetTablePostfix();
const char * GetPlayerDBName();
#endif

382
db/src/Marriage.cpp Normal file
View File

@ -0,0 +1,382 @@
#include "stdafx.h"
#include "Marriage.h"
#include "Main.h"
#include "DBManager.h"
#include "ClientManager.h"
namespace marriage
{
const DWORD WEDDING_LENGTH = 60 * 60; // sec
bool operator < (const TWedding& lhs, const TWedding& rhs)
{
return lhs.dwTime < rhs.dwTime;
}
bool operator > (const TWedding& lhs, const TWedding& rhs)
{
return lhs.dwTime > rhs.dwTime;
}
bool operator > (const TWeddingInfo &lhs, const TWeddingInfo& rhs)
{
return lhs.dwTime > rhs.dwTime;
}
using namespace std;
CManager::CManager()
{
}
CManager::~CManager()
{
}
bool CManager::Initialize()
{
char szQuery[1024];
snprintf(szQuery, sizeof(szQuery),
"SELECT pid1, pid2, love_point, time, is_married, p1.name, p2.name FROM marriage, player%s as p1, player%s as p2 WHERE p1.id = pid1 AND p2.id = pid2",
GetTablePostfix(), GetTablePostfix());
auto_ptr<SQLMsg> pmsg_delete(CDBManager::instance().DirectQuery("DELETE FROM marriage WHERE is_married = 0"));
auto_ptr<SQLMsg> pmsg(CDBManager::instance().DirectQuery(szQuery));
SQLResult * pRes = pmsg->Get();
sys_log(0, "MarriageList(size=%lu)", pRes->uiNumRows);
if (pRes->uiNumRows > 0)
{
for (uint uiRow = 0; uiRow != pRes->uiNumRows; ++uiRow)
{
MYSQL_ROW row = mysql_fetch_row(pRes->pSQLResult);
DWORD pid1 = 0; str_to_number(pid1, row[0]);
DWORD pid2 = 0; str_to_number(pid2, row[1]);
int love_point = 0; str_to_number(love_point, row[2]);
DWORD time = 0; str_to_number(time, row[3]);
BYTE is_married = 0; str_to_number(is_married, row[4]);
const char* name1 = row[5];
const char* name2 = row[6];
TMarriage* pMarriage = new TMarriage(pid1, pid2, love_point, time, is_married, name1, name2);
m_Marriages.insert(pMarriage);
m_MarriageByPID.insert(make_pair(pid1, pMarriage));
m_MarriageByPID.insert(make_pair(pid2, pMarriage));
sys_log(0, "Marriage %lu: LP:%d TM:%u ST:%d %10lu:%16s %10lu:%16s ", uiRow, love_point, time, is_married, pid1, name1, pid2, name2);
}
}
return true;
}
TMarriage* CManager::Get(DWORD dwPlayerID)
{
itertype(m_MarriageByPID) it = m_MarriageByPID.find(dwPlayerID);
if (it != m_MarriageByPID.end())
return it->second;
return NULL;
}
void Align(DWORD& rPID1, DWORD& rPID2)
{
if (rPID1 > rPID2)
std::swap(rPID1, rPID2);
}
void CManager::Add(DWORD dwPID1, DWORD dwPID2, const char* szName1, const char* szName2)
{
DWORD now = CClientManager::instance().GetCurrentTime();
if (IsMarried(dwPID1) || IsMarried(dwPID2))
{
sys_err("cannot marry already married character. %d - %d", dwPID1, dwPID2);
return;
}
Align(dwPID1, dwPID2);
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "INSERT INTO marriage(pid1, pid2, love_point, time) VALUES (%u, %u, 0, %u)", dwPID1, dwPID2, now);
auto_ptr<SQLMsg> pmsg(CDBManager::instance().DirectQuery(szQuery));
SQLResult* res = pmsg->Get();
if (res->uiAffectedRows == 0 || res->uiAffectedRows == (uint32_t)-1)
{
sys_err("cannot insert marriage");
return;
}
sys_log(0, "MARRIAGE ADD %u %u", dwPID1, dwPID2);
TMarriage* pMarriage = new TMarriage(dwPID1, dwPID2, 0, now, 0, szName1, szName2);
m_Marriages.insert(pMarriage);
m_MarriageByPID.insert(make_pair(dwPID1, pMarriage));
m_MarriageByPID.insert(make_pair(dwPID2, pMarriage));
TPacketMarriageAdd p;
p.dwPID1 = dwPID1;
p.dwPID2 = dwPID2;
p.tMarryTime = now;
strlcpy(p.szName1, szName1, sizeof(p.szName1));
strlcpy(p.szName2, szName2, sizeof(p.szName2));
CClientManager::instance().ForwardPacket(HEADER_DG_MARRIAGE_ADD, &p, sizeof(p));
}
void CManager::Update(DWORD dwPID1, DWORD dwPID2, INT iLovePoint, BYTE byMarried)
{
TMarriage* pMarriage = Get(dwPID1);
if (!pMarriage || pMarriage->GetOther(dwPID1) != dwPID2)
{
sys_err("not under marriage : %u %u", dwPID1, dwPID2);
return;
}
Align(dwPID1, dwPID2);
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "UPDATE marriage SET love_point = %d, is_married = %d WHERE pid1 = %u AND pid2 = %u",
iLovePoint, byMarried, pMarriage->pid1, pMarriage->pid2);
auto_ptr<SQLMsg> pmsg(CDBManager::instance().DirectQuery(szQuery));
SQLResult* res = pmsg->Get();
if (res->uiAffectedRows == 0 || res->uiAffectedRows == (uint32_t)-1)
{
sys_err("cannot update marriage : PID:%u %u", dwPID1, dwPID2);
return;
}
sys_log(0, "MARRIAGE UPDATE PID:%u %u LP:%u ST:%d", dwPID1, dwPID2, iLovePoint, byMarried);
pMarriage->love_point = iLovePoint;
pMarriage->is_married = byMarried;
TPacketMarriageUpdate p;
p.dwPID1 = dwPID1;
p.dwPID2 = dwPID2;
p.iLovePoint = pMarriage->love_point;
p.byMarried = pMarriage->is_married;
CClientManager::instance().ForwardPacket(HEADER_DG_MARRIAGE_UPDATE, &p, sizeof(p));
}
void CManager::Remove(DWORD dwPID1, DWORD dwPID2)
{
TMarriage* pMarriage = Get(dwPID1);
if (pMarriage)
{
sys_log(0, "Break Marriage pid1 %d pid2 %d Other %d", dwPID1, dwPID2, pMarriage->GetOther(dwPID1));
}
if (!pMarriage || pMarriage->GetOther(dwPID1) != dwPID2)
{
itertype(m_MarriageByPID) it = m_MarriageByPID.begin();
for (; it != m_MarriageByPID.end(); ++it)
{
sys_log(0, "Marriage List pid1 %d pid2 %d", it->second->pid1, it->second->pid2);
}
sys_err("not under marriage : PID:%u %u", dwPID1, dwPID2);
return;
}
Align(dwPID1, dwPID2);
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "DELETE FROM marriage WHERE pid1 = %u AND pid2 = %u", dwPID1, dwPID2);
auto_ptr<SQLMsg> pmsg(CDBManager::instance().DirectQuery(szQuery));
SQLResult* res = pmsg->Get();
if (res->uiAffectedRows == 0 || res->uiAffectedRows == (uint32_t)-1)
{
sys_err("cannot delete marriage : PID:%u %u", dwPID1, dwPID2);
return;
}
sys_log(0, "MARRIAGE REMOVE PID:%u %u", dwPID1, dwPID2);
m_Marriages.erase(pMarriage);
m_MarriageByPID.erase(dwPID1);
m_MarriageByPID.erase(dwPID2);
TPacketMarriageRemove p;
p.dwPID1 = dwPID1;
p.dwPID2 = dwPID2;
CClientManager::instance().ForwardPacket(HEADER_DG_MARRIAGE_REMOVE, &p, sizeof(p));
delete pMarriage;
}
void CManager::EngageToMarriage(DWORD dwPID1, DWORD dwPID2)
{
TMarriage* pMarriage = Get(dwPID1);
if (!pMarriage || pMarriage->GetOther(dwPID1) != dwPID2)
{
sys_err("not under marriage : PID:%u %u", dwPID1, dwPID2);
return;
}
if (pMarriage->is_married)
{
sys_err("already married, cannot change engage to marry : PID:%u %u", dwPID1, dwPID2);
return;
}
Align(dwPID1, dwPID2);
char szQuery[512];
snprintf(szQuery, sizeof(szQuery), "UPDATE marriage SET is_married = 1 WHERE pid1 = %u AND pid2 = %u",
pMarriage->pid1, pMarriage->pid2);
auto_ptr<SQLMsg> pmsg(CDBManager::instance().DirectQuery(szQuery));
SQLResult* res = pmsg->Get();
if (res->uiAffectedRows == 0 || res->uiAffectedRows == (uint32_t)-1)
{
sys_err("cannot change engage to marriage : PID:%u %u", dwPID1, dwPID2);
return;
}
sys_log(0, "MARRIAGE ENGAGE->MARRIAGE PID:%u %u", dwPID1, dwPID2);
pMarriage->is_married = 1;
TPacketMarriageUpdate p;
p.dwPID1 = dwPID1;
p.dwPID2 = dwPID2;
p.iLovePoint = pMarriage->love_point;
p.byMarried = pMarriage->is_married;
CClientManager::instance().ForwardPacket(HEADER_DG_MARRIAGE_UPDATE, &p, sizeof(p));
}
void CManager::OnSetup(CPeer* peer)
{
// <20><>ȥ<EFBFBD><C8A5> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (itertype(m_Marriages) it = m_Marriages.begin(); it != m_Marriages.end(); ++it)
{
TMarriage* pMarriage = *it;
{
TPacketMarriageAdd p;
p.dwPID1 = pMarriage->pid1;
p.dwPID2 = pMarriage->pid2;
p.tMarryTime = pMarriage->time;
strlcpy(p.szName1, pMarriage->name1.c_str(), sizeof(p.szName1));
strlcpy(p.szName2, pMarriage->name2.c_str(), sizeof(p.szName2));
peer->EncodeHeader(HEADER_DG_MARRIAGE_ADD, 0, sizeof(p));
peer->Encode(&p, sizeof(p));
}
{
TPacketMarriageUpdate p;
p.dwPID1 = pMarriage->pid1;
p.dwPID2 = pMarriage->pid2;
p.iLovePoint = pMarriage->love_point;
p.byMarried = pMarriage->is_married;
peer->EncodeHeader(HEADER_DG_MARRIAGE_UPDATE, 0, sizeof(p));
peer->Encode(&p, sizeof(p));
}
}
// <20><>ȥ<EFBFBD><C8A5> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (itertype(m_mapRunningWedding) it = m_mapRunningWedding.begin(); it != m_mapRunningWedding.end(); ++it)
{
const TWedding& t = it->second;
TPacketWeddingReady p;
p.dwPID1 = t.dwPID1;
p.dwPID2 = t.dwPID2;
p.dwMapIndex = t.dwMapIndex;
peer->EncodeHeader(HEADER_DG_WEDDING_READY, 0, sizeof(p));
peer->Encode(&p, sizeof(p));
TPacketWeddingStart p2;
p2.dwPID1 = t.dwPID1;
p2.dwPID2 = t.dwPID2;
peer->EncodeHeader(HEADER_DG_WEDDING_START, 0, sizeof(p2));
peer->Encode(&p2, sizeof(p2));
}
}
void CManager::ReadyWedding(DWORD dwMapIndex, DWORD dwPID1, DWORD dwPID2)
{
DWORD dwStartTime = CClientManager::instance().GetCurrentTime();
m_pqWeddingStart.push(TWedding(dwStartTime + 5, dwMapIndex, dwPID1, dwPID2));
}
void CManager::EndWedding(DWORD dwPID1, DWORD dwPID2)
{
itertype(m_mapRunningWedding) it = m_mapRunningWedding.find(make_pair(dwPID1, dwPID2));
if (it == m_mapRunningWedding.end())
{
sys_err("try to end wedding %u %u", dwPID1, dwPID2);
return;
}
TWedding& w = it->second;
TPacketWeddingEnd p;
p.dwPID1 = w.dwPID1;
p.dwPID2 = w.dwPID2;
CClientManager::instance().ForwardPacket(HEADER_DG_WEDDING_END, &p, sizeof(p));
m_mapRunningWedding.erase(it);
}
void CManager::Update()
{
DWORD now = CClientManager::instance().GetCurrentTime();
if (!m_pqWeddingEnd.empty())
{
while (!m_pqWeddingEnd.empty() && m_pqWeddingEnd.top().dwTime <= now)
{
TWeddingInfo wi = m_pqWeddingEnd.top();
m_pqWeddingEnd.pop();
itertype(m_mapRunningWedding) it = m_mapRunningWedding.find(make_pair(wi.dwPID1, wi.dwPID2));
if (it == m_mapRunningWedding.end())
continue;
TWedding& w = it->second;
TPacketWeddingEnd p;
p.dwPID1 = w.dwPID1;
p.dwPID2 = w.dwPID2;
CClientManager::instance().ForwardPacket(HEADER_DG_WEDDING_END, &p, sizeof(p));
m_mapRunningWedding.erase(it);
itertype(m_MarriageByPID) it_marriage = m_MarriageByPID.find(w.dwPID1);
if (it_marriage != m_MarriageByPID.end())
{
TMarriage* pMarriage = it_marriage->second;
if (!pMarriage->is_married)
{
Remove(pMarriage->pid1, pMarriage->pid2);
}
}
}
}
if (!m_pqWeddingStart.empty())
{
while (!m_pqWeddingStart.empty() && m_pqWeddingStart.top().dwTime <= now)
{
TWedding w = m_pqWeddingStart.top();
m_pqWeddingStart.pop();
TPacketWeddingStart p;
p.dwPID1 = w.dwPID1;
p.dwPID2 = w.dwPID2;
CClientManager::instance().ForwardPacket(HEADER_DG_WEDDING_START, &p, sizeof(p));
w.dwTime += WEDDING_LENGTH;
m_pqWeddingEnd.push(TWeddingInfo(w.dwTime, w.dwPID1, w.dwPID2));
m_mapRunningWedding.insert(make_pair(make_pair(w.dwPID1, w.dwPID2), w));
}
}
}
}

113
db/src/Marriage.h Normal file
View File

@ -0,0 +1,113 @@
// vim: ts=4 sw=4
#ifndef __MARRIAGE_H
#define __MARRIAGE_H
#include <set>
#include <queue>
#include <deque>
#include "Peer.h"
namespace marriage
{
struct TWeddingInfo
{
DWORD dwTime;
DWORD dwPID1;
DWORD dwPID2;
TWeddingInfo(DWORD time, DWORD pid1, DWORD pid2)
: dwTime(time),
dwPID1(pid1),
dwPID2(pid2)
{
}
};
struct TWedding
{
DWORD dwTime;
DWORD dwMapIndex;
DWORD dwPID1;
DWORD dwPID2;
TWedding(DWORD time, DWORD dwMapIndex, DWORD pid1, DWORD pid2)
: dwTime(time),
dwMapIndex(dwMapIndex),
dwPID1(pid1),
dwPID2(pid2)
{
}
};
extern bool operator < (const TWedding& lhs, const TWedding& rhs);
extern bool operator > (const TWedding& lhs, const TWedding& rhs);
extern bool operator > (const TWeddingInfo& lhs, const TWeddingInfo& rhs);
struct TMarriage
{
DWORD pid1;
DWORD pid2;
int love_point;
DWORD time;
BYTE is_married; // false : <20><>ȥ <20><><EFBFBD><EFBFBD>, true : <20><>ȥ <20><><EFBFBD><EFBFBD>
std::string name1;
std::string name2;
TMarriage(DWORD _pid1, DWORD _pid2, int _love_point, DWORD _time, BYTE _is_married, const char* name1, const char* name2)
: pid1(_pid1), pid2(_pid2), love_point(_love_point), time(_time), is_married(_is_married), name1(name1), name2(name2)
{
}
DWORD GetOther(DWORD PID)
{
if (pid1 == PID)
return pid2;
if (pid2 == PID)
return pid1;
return 0;
}
};
class CManager : public singleton<CManager>
{
public:
CManager();
virtual ~CManager();
bool Initialize();
TMarriage* Get(DWORD dwPlayerID);
bool IsMarried(DWORD dwPlayerID)
{
return Get(dwPlayerID) != NULL;
}
//void Reserve(DWORD dwPID1, DWORD dwPID2);
void Add(DWORD dwPID1, DWORD dwPID2, const char* szName1, const char* szName2);
void Remove(DWORD dwPID1, DWORD dwPID2);
void Update(DWORD dwPID1, DWORD dwPID2, INT iLovePoint, BYTE byMarried);
void EngageToMarriage(DWORD dwPID1, DWORD dwPID2);
void ReadyWedding(DWORD dwMapIndex, DWORD dwPID1, DWORD dwPID2);
void EndWedding(DWORD dwPID1, DWORD dwPID2);
void OnSetup(CPeer* peer);
void Update();
private:
std::set<TMarriage *> m_Marriages;
std::map<DWORD, TMarriage *> m_MarriageByPID;
std::priority_queue<TWedding, std::vector<TWedding>, std::greater<TWedding> > m_pqWeddingStart;
std::priority_queue<TWeddingInfo, std::vector<TWeddingInfo>, std::greater<TWeddingInfo> > m_pqWeddingEnd;
std::map<std::pair<DWORD, DWORD>, TWedding> m_mapRunningWedding;
};
}
#endif

309
db/src/Monarch.cpp Normal file
View File

@ -0,0 +1,309 @@
#include "Monarch.h"
#include "../../common/utils.h"
#include "Main.h"
#include "ClientManager.h"
extern int g_test_server;
CMonarch::CMonarch()
{
memset(&m_MonarchInfo, 0, sizeof(MonarchInfo));
}
CMonarch::~CMonarch()
{
}
bool CMonarch::VoteMonarch(DWORD pid, DWORD selectdpid)
{
MAP_MONARCHELECTION::iterator it = m_map_MonarchElection.find(pid);
if (it == m_map_MonarchElection.end())
{
MonarchElectionInfo * p = new MonarchElectionInfo;
p->pid = pid;
p->selectedpid= selectdpid;
m_map_MonarchElection.insert(MAP_MONARCHELECTION::value_type(pid, p));
char szQuery[256];
snprintf(szQuery, sizeof(szQuery),
"INSERT INTO monarch_election(pid, selectedpid, electiondata) VALUES(%d, %d, now())", pid, selectdpid);
CDBManager::instance().AsyncQuery(szQuery);
return 1;
}
return 0;
}
void CMonarch::ElectMonarch()
{
int size = GetVecMonarchCandidacy().size();
int * s = new int[size];
itertype(m_map_MonarchElection) it = m_map_MonarchElection.begin();
int idx = 0;
for (; it != m_map_MonarchElection.end(); ++it)
{
if ((idx = GetCandidacyIndex(it->second->pid)) < 0)
continue;
++s[idx];
if (g_test_server)
sys_log (0, "[MONARCH_VOTE] pid(%d) come to vote candidacy pid(%d)", it->second->pid, m_vec_MonarchCandidacy[idx].pid);
}
delete [] s;
}
bool CMonarch::IsCandidacy(DWORD pid)
{
VEC_MONARCHCANDIDACY::iterator it = m_vec_MonarchCandidacy.begin();
for (; it != m_vec_MonarchCandidacy.end(); ++it)
{
if (it->pid == pid)
return false;
}
return true;
}
bool CMonarch::AddCandidacy(DWORD pid, const char * name)
{
if (IsCandidacy(pid) == false)
return false;
MonarchCandidacy info;
info.pid = pid;
strlcpy(info.name, name, sizeof(info.name));
m_vec_MonarchCandidacy.push_back(info);
char szQuery[256];
snprintf(szQuery, sizeof(szQuery),
"INSERT INTO monarch_candidacy(pid, date) VALUES(%d, now())", pid);
CDBManager::instance().AsyncQuery(szQuery);
return true;
}
bool CMonarch::DelCandidacy(const char * name)
{
itertype(m_vec_MonarchCandidacy) it = m_vec_MonarchCandidacy.begin();
for (; it != m_vec_MonarchCandidacy.end(); ++it)
{
if (0 == strncmp(it->name, name, sizeof(it->name)))
{
char szQuery[256];
snprintf(szQuery, sizeof(szQuery),
"DELETE FROM monarch_candidacy WHERE pid=%d ", it->pid);
CDBManager::instance().AsyncQuery(szQuery);
m_vec_MonarchCandidacy.erase (it);
return true;
}
}
return false;
}
bool CMonarch::IsMonarch(int Empire, DWORD pid)
{
if (m_MonarchInfo.pid[Empire] != pid)
return false;
return true;
}
bool CMonarch::AddMoney(int Empire, int64_t Money)
{
if (m_MonarchInfo.money[Empire] + Money > 2000000000)
return true;
m_MonarchInfo.money[Empire] += Money;
int64_t Money64 = m_MonarchInfo.money[Empire];
char szQuery[1024];
snprintf(szQuery, sizeof(szQuery), "UPDATE monarch set money=%lld where empire=%d", Money64, Empire);
CDBManager::instance().AsyncQuery(szQuery);
return true;
}
bool CMonarch::DecMoney(int Empire, int64_t Money)
{
if (m_MonarchInfo.money[Empire] - Money < 0)
return false;
m_MonarchInfo.money[Empire] -= Money;
int64_t Money64 = m_MonarchInfo.money[Empire];
char szQuery[1024];
snprintf(szQuery, sizeof(szQuery), "UPDATE monarch set money=%lld where empire=%d", Money64, Empire);
CDBManager::instance().AsyncQuery(szQuery);
return true;
}
bool CMonarch::TakeMoney(int Empire, DWORD pid, int64_t Money)
{
if (IsMonarch(Empire, pid) == false)
return false;
if (m_MonarchInfo.money[Empire] < Money)
return false;
m_MonarchInfo.money[Empire] -= Money;
char szQuery[1024];
snprintf(szQuery, sizeof(szQuery),
"UPDATE monarch set money=%lld; where empire=%d", m_MonarchInfo.money[Empire], Empire);
CDBManager::instance().AsyncQuery(szQuery);
if (g_test_server)
sys_log(0, "[MONARCH] Take money empire(%d) money(%lld)", Empire, m_MonarchInfo.money[Empire]);
return true;
}
bool CMonarch::LoadMonarch()
{
MonarchInfo * p = &m_MonarchInfo;
char szQuery[256];
snprintf(szQuery, sizeof(szQuery), "SELECT empire, pid, name, money, windate FROM monarch a, player%s b where a.pid=b.id", GetTablePostfix());
SQLMsg * pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER);
if (pMsg->Get()->uiNumRows == 0)
{
delete pMsg;
return false;
}
MYSQL_ROW row;
for (int n = 0; (row = mysql_fetch_row(pMsg->Get()->pSQLResult)) != NULL; ++n)
{
int idx = 0;
int Empire = 0; str_to_number(Empire, row[idx++]);
str_to_number(p->pid[Empire], row[idx++]);
strlcpy(p->name[Empire], row[idx++], sizeof(p->name[Empire]));
str_to_number(p->money[Empire], row[idx++]);
strlcpy(p->date[Empire], row[idx++], sizeof(p->date[Empire]));
if (g_test_server)
sys_log(0, "[LOAD_MONARCH] Empire %d pid %d money %lld windate %s", Empire, p->pid[Empire], p->money[Empire], p->date[Empire]);
}
delete pMsg;
return true;
}
bool CMonarch::SetMonarch(const char * name)
{
MonarchInfo * p = &m_MonarchInfo;
char szQuery[256];
snprintf(szQuery, sizeof(szQuery), "SELECT empire, pid, name FROM player a where a.name = '%s'", name);
SQLMsg * pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER);
if (pMsg->Get()->uiNumRows == 0)
{
delete pMsg;
return false;
}
MYSQL_ROW row;
int Empire = 0;
for (int n = 0; (row = mysql_fetch_row(pMsg->Get()->pSQLResult)) != NULL; ++n)
{
int idx = 0;
str_to_number(Empire, row[idx++]);
str_to_number(p->pid[Empire], row[idx++]);
strlcpy(p->name[Empire], row[idx++], sizeof(p->name[Empire]));
p->money[Empire] = atoll(row[idx++]);
if (g_test_server)
sys_log(0, "[Set_MONARCH] Empire %d pid %d money %lld windate %s", Empire, p->pid[Empire], p->money[Empire], p->date[Empire]);
}
delete pMsg;
//db<64><62> <20>Է<EFBFBD>
snprintf(szQuery, sizeof(szQuery),
"REPLACE INTO monarch (empire, name, windate, money) VALUES(%d, %d, now(), %lld)", Empire, p->pid[Empire], p->money[Empire]);
CDBManager::instance().AsyncQuery(szQuery, SQL_PLAYER);
return true;
}
bool CMonarch::DelMonarch(int Empire)
{
char szQuery[256];
snprintf(szQuery, sizeof(szQuery), "DELETE from monarch where empire=%d", Empire);
SQLMsg * pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER);
if (pMsg->Get()->uiNumRows == 0)
{
delete pMsg;
return false;
}
delete pMsg;
memset(m_MonarchInfo.name[Empire], 0, sizeof(m_MonarchInfo.name[Empire]));
m_MonarchInfo.money[Empire] = 0;
m_MonarchInfo.pid[Empire] = 0;
return true;
}
bool CMonarch::DelMonarch(const char * name)
{
for (int n = 1; n < 4; ++n)
{
if (0 == strncmp(m_MonarchInfo.name[n], name, sizeof(m_MonarchInfo.name[n])))
{
char szQuery[256];
int Empire = n;
snprintf(szQuery, sizeof(szQuery), "DELETE from monarch where name=%d", Empire);
SQLMsg * pMsg = CDBManager::instance().DirectQuery(szQuery, SQL_PLAYER);
if (pMsg->Get()->uiNumRows == 0)
{
sys_err(" DirectQuery failed(%s)", szQuery);
delete pMsg;
return false;
}
delete pMsg;
memset(m_MonarchInfo.name[Empire], 0, 32);
m_MonarchInfo.money[Empire] = 0;
m_MonarchInfo.pid[Empire] = 0;
return true;
}
}
return false;
}
int CMonarch::GetCandidacyIndex(DWORD pid)
{
itertype(m_vec_MonarchCandidacy) it = m_vec_MonarchCandidacy.begin();
for (int n = 0; it != m_vec_MonarchCandidacy.end(); ++it, ++n)
{
if (it->pid == pid)
return n;
}
return -1;
}

70
db/src/Monarch.h Normal file
View File

@ -0,0 +1,70 @@
// vim: ts=4 sw=4
#ifndef METIN2_MONARCH_H
#define METIN2_MONARCH_H
#include "../../libthecore/include/stdafx.h"
#include <map>
#include <vector>
#include "../../common/singleton.h"
#include "../../common/tables.h"
class CMonarch : public singleton<CMonarch>
{
public:
typedef std::map<DWORD, MonarchElectionInfo*> MAP_MONARCHELECTION;
typedef std::vector<MonarchCandidacy> VEC_MONARCHCANDIDACY;
CMonarch();
virtual ~CMonarch();
bool VoteMonarch(DWORD pid, DWORD selectedpid);
void ElectMonarch();
bool IsCandidacy(DWORD pid);
bool AddCandidacy(DWORD pid, const char * name);
bool DelCandidacy(const char * name);
bool LoadMonarch();
bool SetMonarch(const char * name);
bool DelMonarch(int Empire);
bool DelMonarch(const char * name);
bool IsMonarch(int Empire, DWORD pid);
bool AddMoney(int Empire, int64_t Money);
bool DecMoney(int Empire, int64_t Money);
bool TakeMoney(int Empire, DWORD pid, int64_t Money);
TMonarchInfo* GetMonarch()
{
return &m_MonarchInfo;
}
VEC_MONARCHCANDIDACY& GetVecMonarchCandidacy()
{
return m_vec_MonarchCandidacy;
}
size_t MonarchCandidacySize()
{
return m_vec_MonarchCandidacy.size();
}
private:
int GetCandidacyIndex(DWORD pid);
MAP_MONARCHELECTION m_map_MonarchElection;
VEC_MONARCHCANDIDACY m_vec_MonarchCandidacy;
TMonarchInfo m_MonarchInfo;
MonarchElectionInfo* GetMonarchElection(DWORD pid)
{
MAP_MONARCHELECTION::iterator it = m_map_MonarchElection.find(pid);
if (it != m_map_MonarchElection.end())
return it->second;
return NULL;
}
};
#endif

57
db/src/MoneyLog.cpp Normal file
View File

@ -0,0 +1,57 @@
#include "stdafx.h"
#include "MoneyLog.h"
#include "ClientManager.h"
#include "Peer.h"
CMoneyLog::CMoneyLog()
{
}
CMoneyLog::~CMoneyLog()
{
}
void CMoneyLog::Save()
{
CPeer* peer = CClientManager::instance().GetAnyPeer();
if (!peer)
return;
for (BYTE bType = 0; bType < MONEY_LOG_TYPE_MAX_NUM; bType ++)
{
typeof(m_MoneyLogContainer[bType].begin()) it;
for (it = m_MoneyLogContainer[bType].begin(); it != m_MoneyLogContainer[bType].end(); ++it)
{
//bType;
TPacketMoneyLog p;
p.type = bType;
p.vnum = it->first;
p.gold = it->second;
peer->EncodeHeader(HEADER_DG_MONEY_LOG, 0, sizeof(p));
peer->Encode(&p, sizeof(p));
}
m_MoneyLogContainer[bType].clear();
}
/*
CPeer* peer = GetPeer();
peer->
for (BYTE bType = 0; bType < MONEY_LOG_TYPE_MAX_NUM; bType++)
{
//"INSERT INTO money_log%s VALUES('%s', %d, %d, %d)", CClientManager::instance().GetTablePostfix(),
typeof(m_MoneyLogContainer[bType].begin()) it;
for (it = m_MoneyLogContainer[bType].begin(); it != m_MoneyLogContainer[bType].end(); ++it)
{
typeof(it->second.begin())
}
}
for (BYTE bType = 0; bType < MONEY_LOG_TYPE_MAX_NUM; bType++)
m_MoneyLogContainer[bType].clear()
*/
}
void CMoneyLog::AddLog(BYTE bType, DWORD dwVnum, int iGold)
{
m_MoneyLogContainer[bType][dwVnum] += iGold;
}

20
db/src/MoneyLog.h Normal file
View File

@ -0,0 +1,20 @@
// vim: ts=8 sw=4
#ifndef __INC_MONEY_LOG
#define __INC_MONEY_LOG
#include <map>
class CMoneyLog : public singleton<CMoneyLog>
{
public:
CMoneyLog();
virtual ~CMoneyLog();
void Save();
void AddLog(BYTE bType, DWORD dwVnum, int iGold);
private:
std::map<DWORD, int> m_MoneyLogContainer[MONEY_LOG_TYPE_MAX_NUM];
};
#endif

54
db/src/NetBase.cpp Normal file
View File

@ -0,0 +1,54 @@
#include "stdafx.h"
#include "NetBase.h"
#include "Config.h"
#include "ClientManager.h"
LPFDWATCH CNetBase::m_fdWatcher = NULL;
CNetBase::CNetBase()
{
}
CNetBase::~CNetBase()
{
}
CNetPoller::CNetPoller()
{
}
CNetPoller::~CNetPoller()
{
Destroy();
}
bool CNetPoller::Create()
{
sys_log(1, "NetPoller::Create()");
if (m_fdWatcher)
return true;
m_fdWatcher = fdwatch_new(512);
if (!m_fdWatcher)
{
Destroy();
return false;
}
return true;
}
void CNetPoller::Destroy()
{
sys_log(1, "NetPoller::Destroy()");
if (m_fdWatcher)
{
fdwatch_delete(m_fdWatcher);
m_fdWatcher = NULL;
}
thecore_destroy();
}

25
db/src/NetBase.h Normal file
View File

@ -0,0 +1,25 @@
// vim: ts=8 sw=4
#ifndef __INC_NETWORKBASE_H__
#define __INC_NETWORKBASE_H__
class CNetBase
{
public:
CNetBase();
virtual ~CNetBase();
protected:
static LPFDWATCH m_fdWatcher;
};
class CNetPoller : public CNetBase, public singleton<CNetPoller>
{
public:
CNetPoller();
virtual ~CNetPoller();
bool Create();
void Destroy();
};
#endif

197
db/src/Peer.cpp Normal file
View File

@ -0,0 +1,197 @@
#include "stdafx.h"
#include "Peer.h"
#include "ItemIDRangeManager.h"
CPeer::CPeer()
{
m_state = 0;
m_bChannel = 0;
m_dwHandle = 0;
m_dwUserCount = 0;
m_wListenPort = 0;
m_wP2PPort = 0;
memset(m_alMaps, 0, sizeof(m_alMaps));
m_itemRange.dwMin = m_itemRange.dwMax = m_itemRange.dwUsableItemIDMin = 0;
m_itemSpareRange.dwMin = m_itemSpareRange.dwMax = m_itemSpareRange.dwUsableItemIDMin = 0;
}
CPeer::~CPeer()
{
Close();
}
void CPeer::OnAccept()
{
m_state = STATE_PLAYING;
static DWORD current_handle = 0;
m_dwHandle = ++current_handle;
sys_log(0, "Connection accepted. (host: %s handle: %u fd: %d)", m_host, m_dwHandle, m_fd);
}
void CPeer::OnConnect()
{
sys_log(0, "Connection established. (host: %s handle: %u fd: %d)", m_host, m_dwHandle, m_fd);
m_state = STATE_PLAYING;
}
void CPeer::OnClose()
{
m_state = STATE_CLOSE;
sys_log(0, "Connection closed. (host: %s)", m_host);
sys_log(0, "ItemIDRange: returned. %u ~ %u", m_itemRange.dwMin, m_itemRange.dwMax);
CItemIDRangeManager::instance().UpdateRange(m_itemRange.dwMin, m_itemRange.dwMax);
m_itemRange.dwMin = 0;
m_itemRange.dwMax = 0;
m_itemRange.dwUsableItemIDMin = 0;
}
DWORD CPeer::GetHandle()
{
return m_dwHandle;
}
DWORD CPeer::GetUserCount()
{
return m_dwUserCount;
}
void CPeer::SetUserCount(DWORD dwCount)
{
m_dwUserCount = dwCount;
}
bool CPeer::PeekPacket(int & iBytesProceed, BYTE & header, DWORD & dwHandle, DWORD & dwLength, const char ** data)
{
if (GetRecvLength() < iBytesProceed + 9)
return false;
const char * buf = (const char *) GetRecvBuffer();
buf += iBytesProceed;
header = *(buf++);
dwHandle = *((DWORD *) buf);
buf += sizeof(DWORD);
dwLength = *((DWORD *) buf);
buf += sizeof(DWORD);
//sys_log(0, "%d header %d handle %u length %u", GetRecvLength(), header, dwHandle, dwLength);
if (iBytesProceed + dwLength + 9 > (DWORD) GetRecvLength())
{
sys_log(0, "PeekPacket: not enough buffer size: len %u, recv %d",
9+dwLength, GetRecvLength()-iBytesProceed);
return false;
}
*data = buf;
iBytesProceed += dwLength + 9;
return true;
}
void CPeer::EncodeHeader(BYTE header, DWORD dwHandle, DWORD dwSize)
{
HEADER h;
sys_log(1, "EncodeHeader %u handle %u size %u", header, dwHandle, dwSize);
h.bHeader = header;
h.dwHandle = dwHandle;
h.dwSize = dwSize;
Encode(&h, sizeof(HEADER));
}
void CPeer::EncodeReturn(BYTE header, DWORD dwHandle)
{
EncodeHeader(header, dwHandle, 0);
}
int CPeer::Send()
{
if (m_state == STATE_CLOSE)
return -1;
return (CPeerBase::Send());
}
void CPeer::SetP2PPort(WORD wPort)
{
m_wP2PPort = wPort;
}
void CPeer::SetMaps(long * pl)
{
thecore_memcpy(m_alMaps, pl, sizeof(m_alMaps));
}
void CPeer::SendSpareItemIDRange()
{
if (m_itemSpareRange.dwMin == 0 || m_itemSpareRange.dwMax == 0 || m_itemSpareRange.dwUsableItemIDMin == 0)
{
EncodeHeader(HEADER_DG_ACK_SPARE_ITEM_ID_RANGE, 0, sizeof(TItemIDRangeTable));
Encode(&m_itemSpareRange, sizeof(TItemIDRangeTable));
}
else
{
SetItemIDRange(m_itemSpareRange);
if (SetSpareItemIDRange(CItemIDRangeManager::instance().GetRange()) == false)
{
sys_log(0, "ItemIDRange: spare range set error");
m_itemSpareRange.dwMin = m_itemSpareRange.dwMax = m_itemSpareRange.dwUsableItemIDMin = 0;
}
EncodeHeader(HEADER_DG_ACK_SPARE_ITEM_ID_RANGE, 0, sizeof(TItemIDRangeTable));
Encode(&m_itemSpareRange, sizeof(TItemIDRangeTable));
}
}
bool CPeer::SetItemIDRange(TItemIDRangeTable itemRange)
{
if (itemRange.dwMin == 0 || itemRange.dwMax == 0 || itemRange.dwUsableItemIDMin == 0) return false;
m_itemRange = itemRange;
sys_log(0, "ItemIDRange: SET %s %u ~ %u start: %u", GetPublicIP(), m_itemRange.dwMin, m_itemRange.dwMax, m_itemRange.dwUsableItemIDMin);
return true;
}
bool CPeer::SetSpareItemIDRange(TItemIDRangeTable itemRange)
{
if (itemRange.dwMin == 0 || itemRange.dwMax == 0 || itemRange.dwUsableItemIDMin == 0) return false;
m_itemSpareRange = itemRange;
sys_log(0, "ItemIDRange: SPARE SET %s %u ~ %u start: %u", GetPublicIP(), m_itemSpareRange.dwMin, m_itemSpareRange.dwMax,
m_itemSpareRange.dwUsableItemIDMin);
return true;
}
bool CPeer::CheckItemIDRangeCollision(TItemIDRangeTable itemRange)
{
if (m_itemRange.dwMin < itemRange.dwMax && m_itemRange.dwMax > itemRange.dwMin)
{
sys_err("ItemIDRange: Collision!! this %u ~ %u check %u ~ %u",
m_itemRange.dwMin, m_itemRange.dwMax, itemRange.dwMin, itemRange.dwMax);
return false;
}
if (m_itemSpareRange.dwMin < itemRange.dwMax && m_itemSpareRange.dwMax > itemRange.dwMin)
{
sys_err("ItemIDRange: Collision with spare range this %u ~ %u check %u ~ %u",
m_itemSpareRange.dwMin, m_itemSpareRange.dwMax, itemRange.dwMin, itemRange.dwMax);
return false;
}
return true;
}

79
db/src/Peer.h Normal file
View File

@ -0,0 +1,79 @@
// vim: ts=8 sw=4
#ifndef __INC_PEER_H__
#define __INC_PEER_H__
#include "PeerBase.h"
class CPeer : public CPeerBase
{
protected:
virtual void OnAccept();
virtual void OnClose();
virtual void OnConnect();
public:
#pragma pack(1)
typedef struct _header
{
BYTE bHeader;
DWORD dwHandle;
DWORD dwSize;
} HEADER;
#pragma pack()
enum EState
{
STATE_CLOSE = 0,
STATE_PLAYING = 1
};
CPeer();
virtual ~CPeer();
void EncodeHeader(BYTE header, DWORD dwHandle, DWORD dwSize);
bool PeekPacket(int & iBytesProceed, BYTE & header, DWORD & dwHandle, DWORD & dwLength, const char ** data);
void EncodeReturn(BYTE header, DWORD dwHandle);
void ProcessInput();
int Send();
DWORD GetHandle();
DWORD GetUserCount();
void SetUserCount(DWORD dwCount);
void SetPublicIP(const char * ip) { m_stPublicIP = ip; }
const char * GetPublicIP() { return m_stPublicIP.c_str(); }
void SetChannel(BYTE bChannel) { m_bChannel = bChannel; }
BYTE GetChannel() { return m_bChannel; }
void SetListenPort(WORD wPort) { m_wListenPort = wPort; }
WORD GetListenPort() { return m_wListenPort; }
void SetP2PPort(WORD wPort);
WORD GetP2PPort() { return m_wP2PPort; }
void SetMaps(long* pl);
long * GetMaps() { return &m_alMaps[0]; }
bool SetItemIDRange(TItemIDRangeTable itemRange);
bool SetSpareItemIDRange(TItemIDRangeTable itemRange);
bool CheckItemIDRangeCollision(TItemIDRangeTable itemRange);
void SendSpareItemIDRange();
private:
int m_state;
BYTE m_bChannel;
DWORD m_dwHandle;
DWORD m_dwUserCount;
WORD m_wListenPort; // <20><><EFBFBD>Ӽ<EFBFBD><D3BC><EFBFBD><EFBFBD><EFBFBD> Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> listen <20>ϴ<EFBFBD> <20><>Ʈ
WORD m_wP2PPort; // <20><><EFBFBD>Ӽ<EFBFBD><D3BC><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>Ӽ<EFBFBD><D3BC><EFBFBD> P2P <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> listen <20>ϴ<EFBFBD> <20><>Ʈ
long m_alMaps[32]; // <20><20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20>ִ°<D6B4>?
TItemIDRangeTable m_itemRange;
TItemIDRangeTable m_itemSpareRange;
std::string m_stPublicIP;
};
#endif

214
db/src/PeerBase.cpp Normal file
View File

@ -0,0 +1,214 @@
#include "stdafx.h"
#include "PeerBase.h"
CPeerBase::CPeerBase() : m_fd(INVALID_SOCKET), m_BytesRemain(0), m_outBuffer(NULL), m_inBuffer(NULL)
{
}
CPeerBase::~CPeerBase()
{
Destroy();
}
void CPeerBase::Disconnect()
{
if (m_fd != INVALID_SOCKET)
{
fdwatch_del_fd(m_fdWatcher, m_fd);
socket_close(m_fd);
m_fd = INVALID_SOCKET;
}
}
void CPeerBase::Destroy()
{
Disconnect();
if (m_outBuffer)
{
buffer_delete(m_outBuffer);
m_outBuffer = NULL;
}
if (m_inBuffer)
{
buffer_delete(m_inBuffer);
m_inBuffer = NULL;
}
}
bool CPeerBase::Accept(socket_t fd_accept)
{
struct sockaddr_in peer;
if ((m_fd = socket_accept(fd_accept, &peer)) == INVALID_SOCKET)
{
Destroy();
return false;
}
//socket_block(m_fd);
socket_sndbuf(m_fd, 233016);
socket_rcvbuf(m_fd, 233016);
strlcpy(m_host, inet_ntoa(peer.sin_addr), sizeof(m_host));
m_outBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE);
m_inBuffer = buffer_new(MAX_INPUT_LEN);
if (!m_outBuffer || !m_inBuffer)
{
Destroy();
return false;
}
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_READ, false);
OnAccept();
sys_log(0, "ACCEPT FROM %s", inet_ntoa(peer.sin_addr));
return true;
}
bool CPeerBase::Connect(const char* host, WORD port)
{
strlcpy(m_host, host, sizeof(m_host));
if ((m_fd = socket_connect(host, port)) == INVALID_SOCKET)
return false;
m_outBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE);
if (!m_outBuffer)
{
Destroy();
return false;
}
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_READ, false);
OnConnect();
return true;
}
void CPeerBase::Close()
{
OnClose();
}
void CPeerBase::EncodeBYTE(BYTE b)
{
if (!m_outBuffer)
{
sys_err("Not ready to write");
return;
}
buffer_write(m_outBuffer, &b, 1);
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}
void CPeerBase::EncodeWORD(WORD w)
{
if (!m_outBuffer)
{
sys_err("Not ready to write");
return;
}
buffer_write(m_outBuffer, &w, 2);
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}
void CPeerBase::EncodeDWORD(DWORD dw)
{
if (!m_outBuffer)
{
sys_err("Not ready to write");
return;
}
buffer_write(m_outBuffer, &dw, 4);
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}
void CPeerBase::Encode(const void* data, DWORD size)
{
if (!m_outBuffer)
{
sys_err("Not ready to write");
return;
}
buffer_write(m_outBuffer, data, size);
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}
int CPeerBase::Recv()
{
if (!m_inBuffer)
{
sys_err("input buffer nil");
return -1;
}
buffer_adjust_size(m_inBuffer, MAX_INPUT_LEN >> 2);
int bytes_to_read = buffer_has_space(m_inBuffer);
ssize_t bytes_read = socket_read(m_fd, (char *) buffer_write_peek(m_inBuffer), bytes_to_read);
if (bytes_read < 0)
{
sys_err("socket_read failed %s", strerror(errno));
return -1;
}
else if (bytes_read == 0)
return 0;
buffer_write_proceed(m_inBuffer, bytes_read);
m_BytesRemain = buffer_size(m_inBuffer);
return 1;
}
void CPeerBase::RecvEnd(int proceed_bytes)
{
buffer_read_proceed(m_inBuffer, proceed_bytes);
m_BytesRemain = buffer_size(m_inBuffer);
}
int CPeerBase::GetRecvLength()
{
return m_BytesRemain;
}
const void * CPeerBase::GetRecvBuffer()
{
return buffer_read_peek(m_inBuffer);
}
int CPeerBase::GetSendLength()
{
return buffer_size(m_outBuffer);
}
int CPeerBase::Send()
{
if (buffer_size(m_outBuffer) <= 0)
return 0;
int iBufferLeft = fdwatch_get_buffer_size(m_fdWatcher, m_fd);
int iBytesToWrite = MIN(iBufferLeft, buffer_size(m_outBuffer));
if (iBytesToWrite == 0)
return 0;
int result = socket_write(m_fd, (const char *) buffer_read_peek(m_outBuffer), iBytesToWrite);
if (result == 0)
{
buffer_read_proceed(m_outBuffer, iBytesToWrite);
if (buffer_size(m_outBuffer) != 0)
fdwatch_add_fd(m_fdWatcher, m_fd, this, FDW_WRITE, true);
}
return (result);
}

61
db/src/PeerBase.h Normal file
View File

@ -0,0 +1,61 @@
// vim: ts=8 sw=4
#ifndef __INC_PEERBASE_H__
#define __INC_PEERBASE_H__
#include "NetBase.h"
class CPeerBase : public CNetBase
{
public:
enum
{
MAX_HOST_LENGTH = 30,
MAX_INPUT_LEN = 1024 * 1024 * 2,
DEFAULT_PACKET_BUFFER_SIZE = 1024 * 1024 * 2
};
protected:
virtual void OnAccept() = 0;
virtual void OnConnect() = 0;
virtual void OnClose() = 0;
public:
bool Accept(socket_t accept_fd);
bool Connect(const char* host, WORD port);
void Close();
public:
CPeerBase();
virtual ~CPeerBase();
void Disconnect();
void Destroy();
socket_t GetFd() { return m_fd; }
void EncodeBYTE(BYTE b);
void EncodeWORD(WORD w);
void EncodeDWORD(DWORD dw);
void Encode(const void* data, DWORD size);
int Send();
int Recv();
void RecvEnd(int proceed_bytes);
int GetRecvLength();
const void * GetRecvBuffer();
int GetSendLength();
const char * GetHost() { return m_host; }
protected:
char m_host[MAX_HOST_LENGTH + 1];
socket_t m_fd;
private:
int m_BytesRemain;
LPBUFFER m_outBuffer;
LPBUFFER m_inBuffer;
};
#endif

291
db/src/PrivManager.cpp Normal file
View File

@ -0,0 +1,291 @@
#include "stdafx.h"
#include "PrivManager.h"
#include "ClientManager.h"
const int PRIV_DURATION = 60*60*12;
const int CHARACTER_GOOD_PRIV_DURATION = 2*60*60;
const int CHARACTER_BAD_PRIV_DURATION = 60*60;
CPrivManager::CPrivManager()
{
for (int type = 0; type < MAX_PRIV_NUM; ++type)
{
for (int empire = 0; empire < EMPIRE_MAX_NUM; ++empire)
m_aaPrivEmpire[type][empire] = 0;
}
}
CPrivManager::~CPrivManager()
{
}
//
// @version 05/06/07 Bang2ni - <20>ߺ<EFBFBD><DFBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><20><><EFBFBD><EFBFBD> ó<><C3B3>
//
void CPrivManager::Update()
{
time_t now = CClientManager::instance().GetCurrentTime();
while (!m_pqPrivGuild.empty() && m_pqPrivGuild.top().first <= now)
{
TPrivGuildData* p = m_pqPrivGuild.top().second;
m_pqPrivGuild.pop();
if (p->value != 0 && !p->bRemoved)
{
typeof(m_aPrivGuild[p->type].begin()) it = m_aPrivGuild[p->type].find(p->guild_id);
// ADD_GUILD_PRIV_TIME
// <20><><EFBFBD><20>ߺ<EFBFBD><DFBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD> <20><><EFBFBD><EFBFBD> map <20><> value <20><> <20><><EFBFBD><EFBFBD>(<28><><EFBFBD><EFBFBD>) <20>Ǿ<EFBFBD><C7BE><EFBFBD><EFBFBD>Ƿ<EFBFBD>
// TPrivGuildData <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ͱ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ְ<EFBFBD> <20><><EFBFBD>Ӽ<EFBFBD><D3BC><EFBFBD><EFBFBD><EFBFBD><E9BFA1> cast <20><> <20>ش<EFBFBD>.
if (it != m_aPrivGuild[p->type].end() && it->second == p) {
m_aPrivGuild[p->type].erase(it);
SendChangeGuildPriv(p->guild_id, p->type, 0, 0);
// END_OF_ADD_GUILD_PRIV_TIME
}
}
delete p;
}
while (!m_pqPrivEmpire.empty() && m_pqPrivEmpire.top().first <= now)
{
TPrivEmpireData* p = (m_pqPrivEmpire.top().second);
m_pqPrivEmpire.pop();
if (p->value != 0 && !p->bRemoved)
{
SendChangeEmpirePriv(p->empire, p->type, 0, 0);
m_aaPrivEmpire[p->type][p->empire] = 0;
}
delete p;
}
while (!m_pqPrivChar.empty() && m_pqPrivChar.top().first <= now)
{
TPrivCharData* p = (m_pqPrivChar.top().second);
m_pqPrivChar.pop();
if (!p->bRemoved)
{
// TODO send packet
SendChangeCharPriv(p->pid, p->type, 0);
typeof(m_aPrivChar[p->type].begin()) it = m_aPrivChar[p->type].find(p->pid);
if (it != m_aPrivChar[p->type].end())
m_aPrivChar[p->type].erase(it);
}
delete p;
}
}
void CPrivManager::AddCharPriv(DWORD pid, BYTE type, int value)
{
if (MAX_PRIV_NUM <= type)
{
sys_err("PRIV_MANAGER: AddCharPriv: wrong char priv type(%u) recved", type);
return;
}
typeof(m_aPrivChar[type].begin()) it = m_aPrivChar[type].find(pid);
if (it != m_aPrivChar[type].end())
return;
if (!value)
return;
time_t now = CClientManager::instance().GetCurrentTime();
TPrivCharData* p = new TPrivCharData(type, value, pid);
int iDuration = CHARACTER_BAD_PRIV_DURATION;
if (value > 0)
iDuration = CHARACTER_GOOD_PRIV_DURATION;
m_pqPrivChar.push(std::make_pair(now+iDuration, p));
m_aPrivChar[type].insert(std::make_pair(pid, p));
// TODO send packet
sys_log(0, "AddCharPriv %d %d %d", pid, type, value);
SendChangeCharPriv(pid, type, value);
}
//
// @version 05/06/07 Bang2ni - <20>̹<EFBFBD> <20><><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><20><><EFBFBD>ʽ<EFBFBD> <20><><EFBFBD><EFBFBD>
//
void CPrivManager::AddGuildPriv(DWORD guild_id, BYTE type, int value, time_t duration_sec)
{
if (MAX_PRIV_NUM <= type)
{
sys_err("PRIV_MANAGER: AddGuildPriv: wrong guild priv type(%u) recved", type);
return;
}
typeof(m_aPrivGuild[type].begin()) it = m_aPrivGuild[type].find(guild_id);
time_t now = CClientManager::instance().GetCurrentTime();
time_t end = now + duration_sec;
TPrivGuildData * p = new TPrivGuildData(type, value, guild_id, end);
m_pqPrivGuild.push(std::make_pair(end, p));
// ADD_GUILD_PRIV_TIME
// <20>̹<EFBFBD> <20><><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִٸ<D6B4> map <20><> value <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ش<EFBFBD>.
// <20><><EFBFBD><EFBFBD> value <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD> priority queue <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD>.
if (it != m_aPrivGuild[type].end())
it->second = p;
else
m_aPrivGuild[type].insert(std::make_pair(guild_id, p));
SendChangeGuildPriv(guild_id, type, value, end);
// END_OF_ADD_GUILD_PRIV_TIME
sys_log(0, "Guild Priv guild(%d) type(%d) value(%d) duration_sec(%d)", guild_id, type, value, duration_sec);
}
void CPrivManager::AddEmpirePriv(BYTE empire, BYTE type, int value, time_t duration_sec)
{
if (MAX_PRIV_NUM <= type)
{
sys_err("PRIV_MANAGER: AddEmpirePriv: wrong empire priv type(%u) recved", type);
return;
}
if (duration_sec < 0)
duration_sec = 0;
time_t now = CClientManager::instance().GetCurrentTime();
time_t end = now+duration_sec;
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȿȭ
// priority_queue<75><65> <20><><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD> pointer == m_aaPrivEmpire[type][empire]
{
if (m_aaPrivEmpire[type][empire])
m_aaPrivEmpire[type][empire]->bRemoved = true;
}
TPrivEmpireData * p = new TPrivEmpireData(type, value, empire, end);
m_pqPrivEmpire.push(std::make_pair(end, p));
m_aaPrivEmpire[type][empire] = p;
// ADD_EMPIRE_PRIV_TIME
SendChangeEmpirePriv(empire, type, value, end);
// END_OF_ADD_EMPIRE_PRIV_TIME
sys_log(0, "Empire Priv empire(%d) type(%d) value(%d) duration_sec(%d)", empire, type, value, duration_sec);
}
/**
* @version 05/06/08 Bang2ni - <20><><EFBFBD>ӽð<D3BD> <20>߰<EFBFBD>
*/
struct FSendChangeGuildPriv
{
FSendChangeGuildPriv(DWORD guild_id, BYTE type, int value, time_t end_time_sec)
{
p.guild_id = guild_id;
p.type = type;
p.value = value;
p.bLog = 1;
// ADD_GUILD_PRIV_TIME
p.end_time_sec = end_time_sec;
// END_OF_ADD_GUILD_PRIV_TIME
}
void operator() (CPeer* peer)
{
peer->EncodeHeader(HEADER_DG_CHANGE_GUILD_PRIV, 0, sizeof(TPacketDGChangeGuildPriv));
peer->Encode(&p, sizeof(TPacketDGChangeGuildPriv));
p.bLog = 0;
}
TPacketDGChangeGuildPriv p;
};
struct FSendChangeEmpirePriv
{
FSendChangeEmpirePriv(BYTE empire, BYTE type, int value, time_t end_time_sec)
{
p.empire = empire;
p.type = type;
p.value = value;
p.bLog = 1;
// ADD_EMPIRE_PRIV_TIME
p.end_time_sec = end_time_sec;
// END_OF_ADD_EMPIRE_PRIV_TIME
}
void operator ()(CPeer* peer)
{
peer->EncodeHeader(HEADER_DG_CHANGE_EMPIRE_PRIV, 0, sizeof(TPacketDGChangeEmpirePriv));
peer->Encode(&p, sizeof(TPacketDGChangeEmpirePriv));
p.bLog = 0;
}
TPacketDGChangeEmpirePriv p;
};
struct FSendChangeCharPriv
{
FSendChangeCharPriv(DWORD pid, BYTE type, int value)
{
p.pid = pid;
p.type = type;
p.value = value;
p.bLog = 1;
}
void operator()(CPeer* peer)
{
peer->EncodeHeader(HEADER_DG_CHANGE_CHARACTER_PRIV, 0, sizeof(TPacketDGChangeCharacterPriv));
peer->Encode(&p, sizeof(TPacketDGChangeCharacterPriv));
p.bLog = 0;
}
TPacketDGChangeCharacterPriv p;
};
// ADD_GUILD_PRIV_TIME
void CPrivManager::SendChangeGuildPriv(DWORD guild_id, BYTE type, int value, time_t end_time_sec)
{
CClientManager::instance().for_each_peer(FSendChangeGuildPriv(guild_id, type, value, end_time_sec));
}
// END_OF_ADD_GUILD_PRIV_TIME
// ADD_EMPIRE_PRIV_TIME
void CPrivManager::SendChangeEmpirePriv(BYTE empire, BYTE type, int value, time_t end_time_sec)
{
CClientManager::instance().for_each_peer(FSendChangeEmpirePriv(empire, type, value, end_time_sec));
}
// END_OF_ADD_EMPIRE_PRIV_TIME
void CPrivManager::SendChangeCharPriv(DWORD pid, BYTE type, int value)
{
CClientManager::instance().for_each_peer(FSendChangeCharPriv(pid, type, value));
}
void CPrivManager::SendPrivOnSetup(CPeer* peer)
{
for (int i = 1; i < MAX_PRIV_NUM; ++i)
{
for (int e = 0; e < EMPIRE_MAX_NUM; ++e)
{
// ADD_EMPIRE_PRIV_TIME
TPrivEmpireData* pPrivEmpireData = m_aaPrivEmpire[i][e];
if (pPrivEmpireData)
{
FSendChangeEmpirePriv(e, i, pPrivEmpireData->value, pPrivEmpireData->end_time_sec)(peer);
}
// END_OF_ADD_EMPIRE_PRIV_TIME
}
for (typeof(m_aPrivGuild[i].begin()) it = m_aPrivGuild[i].begin(); it != m_aPrivGuild[i].end();++it)
{
// ADD_GUILD_PRIV_TIME
FSendChangeGuildPriv(it->first, i, it->second->value, it->second->end_time_sec)(peer);
// END_OF_ADD_GUILD_PRIV_TIME
}
for (typeof(m_aPrivChar[i].begin()) it = m_aPrivChar[i].begin(); it != m_aPrivChar[i].end(); ++it)
{
FSendChangeCharPriv(it->first, i, it->second->value)(peer);
}
}
}

106
db/src/PrivManager.h Normal file
View File

@ -0,0 +1,106 @@
// vim: ts=8 sw=4
#ifndef __INC_PRIV_MANAGER_H
#define __INC_PRIV_MANAGER_H
#include "Peer.h"
#include <queue>
#include <utility>
struct TPrivEmpireData
{
BYTE type;
int value;
bool bRemoved;
BYTE empire;
// ADD_EMPIRE_PRIV_TIME
time_t end_time_sec;
TPrivEmpireData(BYTE type, int value, BYTE empire, time_t end_time_sec)
: type(type), value(value), bRemoved(false), empire(empire), end_time_sec(end_time_sec)
{}
// END_OF_ADD_EMPIRE_PRIV_TIME
};
/**
* @version 05/06/08 Bang2ni - <20><><EFBFBD>ӽð<D3BD> <20>߰<EFBFBD>
*/
struct TPrivGuildData
{
BYTE type;
int value;
bool bRemoved;
DWORD guild_id;
// ADD_GUILD_PRIV_TIME
time_t end_time_sec; ///< <20><><EFBFBD>ӽð<D3BD>
TPrivGuildData(BYTE type, int value, DWORD guild_id, time_t _end_time_sec)
: type(type), value(value), bRemoved(false), guild_id(guild_id), end_time_sec(_end_time_sec )
{}
// END_OF_ADD_GUILD_PRIV_TIME
};
struct TPrivCharData
{
BYTE type;
int value;
bool bRemoved;
DWORD pid;
TPrivCharData(BYTE type, int value, DWORD pid)
: type(type), value(value), bRemoved(false), pid(pid)
{}
};
/**
* @version 05/06/08 Bang2ni - Guild privilege <20><><EFBFBD><EFBFBD> <20>Լ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ð<EFBFBD> <20>߰<EFBFBD>
*/
class CPrivManager : public singleton<CPrivManager>
{
public:
CPrivManager();
virtual ~CPrivManager();
// ADD_GUILD_PRIV_TIME
void AddGuildPriv(DWORD guild_id, BYTE type, int value, time_t time_sec);
// END_OF_ADD_GUILD_PRIV_TIME
// ADD_EMPIRE_PRIV_TIME
void AddEmpirePriv(BYTE empire, BYTE type, int value, time_t time_sec);
// END_OF_ADD_EMPIRE_PRIV_TIME
void AddCharPriv(DWORD pid, BYTE type, int value);
void Update();
void SendPrivOnSetup(CPeer* peer);
private:
// ADD_GUILD_PRIV_TIME
void SendChangeGuildPriv(DWORD guild_id, BYTE type, int value, time_t end_time_sec);
// END_OF_ADD_GUILD_PRIV_TIME
// ADD_EMPIRE_PRIV_TIME
void SendChangeEmpirePriv(BYTE empire, BYTE type, int value, time_t end_time_sec);
// END_OF_ADD_EMPIRE_PRIV_TIME
void SendChangeCharPriv(DWORD pid, BYTE type, int value);
typedef std::pair<time_t, TPrivCharData *> stPairChar;
typedef std::pair<time_t, TPrivGuildData*> stPairGuild;
typedef std::pair<time_t, TPrivEmpireData*> stPairEmpire;
std::priority_queue<stPairChar, std::vector<stPairChar>, std::greater<stPairChar> >
m_pqPrivChar;
std::priority_queue<stPairGuild, std::vector<stPairGuild>, std::greater<stPairGuild> >
m_pqPrivGuild;
std::priority_queue<stPairEmpire, std::vector<stPairEmpire>, std::greater<stPairEmpire> >
m_pqPrivEmpire;
TPrivEmpireData* m_aaPrivEmpire[MAX_PRIV_NUM][EMPIRE_MAX_NUM];
std::map<DWORD, TPrivGuildData*> m_aPrivGuild[MAX_PRIV_NUM];
std::map<DWORD, TPrivCharData*> m_aPrivChar[MAX_PRIV_NUM];
};
#endif

838
db/src/ProtoReader.cpp Normal file
View File

@ -0,0 +1,838 @@
#include "stdafx.h"
#include <math.h>
#include "ProtoReader.h"
#include "CsvReader.h"
#include <sstream>
using namespace std;
inline string trim_left(const string& str)
{
string::size_type n = str.find_first_not_of(" \t\v\n\r");
return n == string::npos ? str : str.substr(n, str.length());
}
inline string trim_right(const string& str)
{
string::size_type n = str.find_last_not_of(" \t\v\n\r");
return n == string::npos ? str : str.substr(0, n + 1);
}
string trim(const string& str){return trim_left(trim_right(str));}
static string* StringSplit(string strOrigin, string strTok)
{
int cutAt; //<2F>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD>ġ
int index = 0; //<2F><><EFBFBD>ڿ<EFBFBD><DABF>ε<EFBFBD><CEB5><EFBFBD>
string* strResult = new string[30]; //<2F><><EFBFBD><EFBFBD>return <20>Һ<EFBFBD><D2BA><EFBFBD>
//strTok<6F><6B>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݺ<EFBFBD>
while ((cutAt = strOrigin.find_first_of(strTok)) != strOrigin.npos)
{
if (cutAt > 0) //<2F>ڸ<EFBFBD><DAB8><EFBFBD><EFBFBD><EFBFBD>ġ<EFBFBD><C4A1>0<EFBFBD><30><EFBFBD><EFBFBD>ũ<EFBFBD><C5A9>(<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
{
strResult[index++] = strOrigin.substr(0, cutAt); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8BFAD><EFBFBD>߰<EFBFBD>
}
strOrigin = strOrigin.substr(cutAt+1); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD><DAB8>κ<EFBFBD><CEBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѳ<EFBFBD><D1B3><EFBFBD><EFBFBD><EFBFBD>
}
if(strOrigin.length() > 0) //<2F><><EFBFBD><EFBFBD><EFBFBD>̾<EFBFBD><CCBE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
strResult[index++] = strOrigin.substr(0, cutAt); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8BFAD><EFBFBD>߰<EFBFBD>
}
for( int i=0;i<index;i++)
{
strResult[i] = trim(strResult[i]);
}
return strResult; //<2F><><EFBFBD><EFBFBD>return
}
int get_Item_Type_Value(string inputString)
{
string arType[] = {"ITEM_NONE", "ITEM_WEAPON",
"ITEM_ARMOR", "ITEM_USE",
"ITEM_AUTOUSE", "ITEM_MATERIAL",
"ITEM_SPECIAL", "ITEM_TOOL",
"ITEM_LOTTERY", "ITEM_ELK", //10<31><30>
"ITEM_METIN", "ITEM_CONTAINER",
"ITEM_FISH", "ITEM_ROD",
"ITEM_RESOURCE", "ITEM_CAMPFIRE",
"ITEM_UNIQUE", "ITEM_SKILLBOOK",
"ITEM_QUEST", "ITEM_POLYMORPH", //20<32><30>
"ITEM_TREASURE_BOX", "ITEM_TREASURE_KEY",
"ITEM_SKILLFORGET", "ITEM_GIFTBOX",
"ITEM_PICK", "ITEM_HAIR",
"ITEM_TOTEM", "ITEM_BLEND",
"ITEM_COSTUME", "ITEM_DS", //30<33><30>
"ITEM_SPECIAL_DS", "ITEM_EXTRACT",
"ITEM_SECONDARY_COIN", //33<33><33>
"ITEM_RING",
"ITEM_BELT", //35<33><35> (EItemTypes <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ġ<><C4A1> 34)
};
int retInt = -1;
//cout << "Type : " << typeStr << " -> ";
for (int j=0;j<sizeof(arType)/sizeof(arType[0]);j++) {
string tempString = arType[j];
if (inputString.find(tempString)!=string::npos && tempString.find(inputString)!=string::npos) {
//cout << j << " ";
retInt = j;
break;
}
}
//cout << endl;
return retInt;
}
int get_Item_SubType_Value(int type_value, string inputString)
{
static string arSub1[] = { "WEAPON_SWORD", "WEAPON_DAGGER", "WEAPON_BOW", "WEAPON_TWO_HANDED",
"WEAPON_BELL", "WEAPON_FAN", "WEAPON_ARROW", "WEAPON_MOUNT_SPEAR"};
static string arSub2[] = { "ARMOR_BODY", "ARMOR_HEAD", "ARMOR_SHIELD", "ARMOR_WRIST", "ARMOR_FOOTS",
"ARMOR_NECK", "ARMOR_EAR", "ARMOR_NUM_TYPES"};
static string arSub3[] = { "USE_POTION", "USE_TALISMAN", "USE_TUNING", "USE_MOVE", "USE_TREASURE_BOX", "USE_MONEYBAG", "USE_BAIT",
"USE_ABILITY_UP", "USE_AFFECT", "USE_CREATE_STONE", "USE_SPECIAL", "USE_POTION_NODELAY", "USE_CLEAR",
"USE_INVISIBILITY", "USE_DETACHMENT", "USE_BUCKET", "USE_POTION_CONTINUE", "USE_CLEAN_SOCKET",
"USE_CHANGE_ATTRIBUTE", "USE_ADD_ATTRIBUTE", "USE_ADD_ACCESSORY_SOCKET", "USE_PUT_INTO_ACCESSORY_SOCKET",
"USE_ADD_ATTRIBUTE2", "USE_RECIPE", "USE_CHANGE_ATTRIBUTE2", "USE_BIND", "USE_UNBIND", "USE_TIME_CHARGE_PER", "USE_TIME_CHARGE_FIX", "USE_PUT_INTO_BELT_SOCKET", "USE_PUT_INTO_RING_SOCKET"};
static string arSub4[] = { "AUTOUSE_POTION", "AUTOUSE_ABILITY_UP", "AUTOUSE_BOMB", "AUTOUSE_GOLD", "AUTOUSE_MONEYBAG", "AUTOUSE_TREASURE_BOX"};
static string arSub5[] = { "MATERIAL_LEATHER", "MATERIAL_BLOOD", "MATERIAL_ROOT", "MATERIAL_NEEDLE", "MATERIAL_JEWEL",
"MATERIAL_DS_REFINE_NORMAL", "MATERIAL_DS_REFINE_BLESSED", "MATERIAL_DS_REFINE_HOLLY"};
static string arSub6[] = { "SPECIAL_MAP", "SPECIAL_KEY", "SPECIAL_DOC", "SPECIAL_SPIRIT"};
static string arSub7[] = { "TOOL_FISHING_ROD" };
static string arSub8[] = { "LOTTERY_TICKET", "LOTTERY_INSTANT" };
static string arSub10[] = { "METIN_NORMAL", "METIN_GOLD" };
static string arSub12[] = { "FISH_ALIVE", "FISH_DEAD"};
static string arSub14[] = { "RESOURCE_FISHBONE", "RESOURCE_WATERSTONEPIECE", "RESOURCE_WATERSTONE", "RESOURCE_BLOOD_PEARL",
"RESOURCE_BLUE_PEARL", "RESOURCE_WHITE_PEARL", "RESOURCE_BUCKET", "RESOURCE_CRYSTAL", "RESOURCE_GEM",
"RESOURCE_STONE", "RESOURCE_METIN", "RESOURCE_ORE" };
static string arSub16[] = { "UNIQUE_NONE", "UNIQUE_BOOK", "UNIQUE_SPECIAL_RIDE", "UNIQUE_3", "UNIQUE_4", "UNIQUE_5",
"UNIQUE_6", "UNIQUE_7", "UNIQUE_8", "UNIQUE_9", "USE_SPECIAL"};
static string arSub28[] = { "COSTUME_BODY", "COSTUME_HAIR" };
static string arSub29[] = { "DS_SLOT1", "DS_SLOT2", "DS_SLOT3", "DS_SLOT4", "DS_SLOT5", "DS_SLOT6" };
static string arSub31[] = { "EXTRACT_DRAGON_SOUL", "EXTRACT_DRAGON_HEART" };
static string* arSubType[] = {0, //0
arSub1, //1
arSub2, //2
arSub3, //3
arSub4, //4
arSub5, //5
arSub6, //6
arSub7, //7
arSub8, //8
0, //9
arSub10, //10
0, //11
arSub12, //12
0, //13
arSub14, //14
0, //15
arSub16, //16
0, //17
0, //18
0, //19
0, //20
0, //21
0, //22
0, //23
0, //24
0, //25
0, //26
0, //27
arSub28, //28
arSub29, //29
arSub29, //30
arSub31, //31
0, //32
0, //33 <20><><EFBFBD><EFBFBD>
0, //34 <20><>Ʈ
};
static int arNumberOfSubtype[_countof(arSubType)] = {
0,
sizeof(arSub1)/sizeof(arSub1[0]),
sizeof(arSub2)/sizeof(arSub2[0]),
sizeof(arSub3)/sizeof(arSub3[0]),
sizeof(arSub4)/sizeof(arSub4[0]),
sizeof(arSub5)/sizeof(arSub5[0]),
sizeof(arSub6)/sizeof(arSub6[0]),
sizeof(arSub7)/sizeof(arSub7[0]),
sizeof(arSub8)/sizeof(arSub8[0]),
0,
sizeof(arSub10)/sizeof(arSub10[0]),
0,
sizeof(arSub12)/sizeof(arSub12[0]),
0,
sizeof(arSub14)/sizeof(arSub14[0]),
0,
sizeof(arSub16)/sizeof(arSub16[0]),
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
sizeof(arSub28)/sizeof(arSub28[0]),
sizeof(arSub29)/sizeof(arSub29[0]),
sizeof(arSub29)/sizeof(arSub29[0]),
sizeof(arSub31)/sizeof(arSub31[0]),
0, // 32
0, // 33 <20><><EFBFBD><EFBFBD>
0, // 34 <20><>Ʈ
};
assert(_countof(arSubType) > type_value && "Subtype rule: Out of range!!");
// assert <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>..
if (_countof(arSubType) <= type_value)
{
sys_err("SubType : Out of range!! (type_value: %d, count of registered subtype: %d", type_value, _countof(arSubType));
return -1;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ÿ<><C5B8><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ÿ<EFBFBD><C5B8> <20><EFBFBD>̰<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD> <20>˾ƺ<CBBE><C6BA><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0 <20><><EFBFBD><EFBFBD>
if (arSubType[type_value]==0) {
return 0;
}
//
int retInt = -1;
//cout << "SubType : " << subTypeStr << " -> ";
for (int j=0;j<arNumberOfSubtype[type_value];j++) {
string tempString = arSubType[type_value][j];
string tempInputString = trim(inputString);
if (tempInputString.compare(tempString)==0)
{
//cout << j << " ";
retInt = j;
break;
}
}
//cout << endl;
return retInt;
}
int get_Item_AntiFlag_Value(string inputString)
{
string arAntiFlag[] = {"ANTI_FEMALE", "ANTI_MALE", "ANTI_MUSA", "ANTI_ASSASSIN", "ANTI_SURA", "ANTI_MUDANG",
"ANTI_GET", "ANTI_DROP", "ANTI_SELL", "ANTI_EMPIRE_A", "ANTI_EMPIRE_B", "ANTI_EMPIRE_C",
"ANTI_SAVE", "ANTI_GIVE", "ANTI_PKDROP", "ANTI_STACK", "ANTI_MYSHOP", "ANTI_SAFEBOX"};
int retValue = 0;
string* arInputString = StringSplit(inputString, "|"); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ܾ<DCBE><EEBAB0> <20>ɰ<EFBFBD> <20>迭.
for(int i =0;i<sizeof(arAntiFlag)/sizeof(arAntiFlag[0]);i++) {
string tempString = arAntiFlag[i];
for (int j=0; j<30 ; j++) //<2F>ִ<EFBFBD> 30<33><30> <20>ܾ<EFBFBD><DCBE><EFBFBD><EFBFBD><EFBFBD>. (<28>ϵ<EFBFBD><CFB5>ڵ<EFBFBD>)
{
string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //<2F><>ġ<EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD> Ȯ<><C8AE>.
retValue = retValue + pow((float)2,(float)i);
}
if(tempString2.compare("") == 0)
break;
}
}
delete []arInputString;
//cout << "AntiFlag : " << antiFlagStr << " -> " << retValue << endl;
return retValue;
}
int get_Item_Flag_Value(string inputString)
{
string arFlag[] = {"ITEM_TUNABLE", "ITEM_SAVE", "ITEM_STACKABLE", "COUNT_PER_1GOLD", "ITEM_SLOW_QUERY", "ITEM_UNIQUE",
"ITEM_MAKECOUNT", "ITEM_IRREMOVABLE", "CONFIRM_WHEN_USE", "QUEST_USE", "QUEST_USE_MULTIPLE",
"QUEST_GIVE", "ITEM_QUEST", "LOG", "STACKABLE", "SLOW_QUERY", "REFINEABLE", "IRREMOVABLE", "ITEM_APPLICABLE"};
int retValue = 0;
string* arInputString = StringSplit(inputString, "|"); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ܾ<DCBE><EEBAB0> <20>ɰ<EFBFBD> <20>迭.
for(int i =0;i<sizeof(arFlag)/sizeof(arFlag[0]);i++) {
string tempString = arFlag[i];
for (int j=0; j<30 ; j++) //<2F>ִ<EFBFBD> 30<33><30> <20>ܾ<EFBFBD><DCBE><EFBFBD><EFBFBD><EFBFBD>. (<28>ϵ<EFBFBD><CFB5>ڵ<EFBFBD>)
{
string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //<2F><>ġ<EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD> Ȯ<><C8AE>.
retValue = retValue + pow((float)2,(float)i);
}
if(tempString2.compare("") == 0)
break;
}
}
delete []arInputString;
//cout << "Flag : " << flagStr << " -> " << retValue << endl;
return retValue;
}
int get_Item_WearFlag_Value(string inputString)
{
string arWearrFlag[] = {"WEAR_BODY", "WEAR_HEAD", "WEAR_FOOTS", "WEAR_WRIST", "WEAR_WEAPON", "WEAR_NECK", "WEAR_EAR", "WEAR_SHIELD", "WEAR_UNIQUE",
"WEAR_ARROW", "WEAR_HAIR", "WEAR_ABILITY"};
int retValue = 0;
string* arInputString = StringSplit(inputString, "|"); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ܾ<DCBE><EEBAB0> <20>ɰ<EFBFBD> <20>迭.
for(int i =0;i<sizeof(arWearrFlag)/sizeof(arWearrFlag[0]);i++) {
string tempString = arWearrFlag[i];
for (int j=0; j<30 ; j++) //<2F>ִ<EFBFBD> 30<33><30> <20>ܾ<EFBFBD><DCBE><EFBFBD><EFBFBD><EFBFBD>. (<28>ϵ<EFBFBD><CFB5>ڵ<EFBFBD>)
{
string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //<2F><>ġ<EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD> Ȯ<><C8AE>.
retValue = retValue + pow((float)2,(float)i);
}
if(tempString2.compare("") == 0)
break;
}
}
delete []arInputString;
//cout << "WearFlag : " << wearFlagStr << " -> " << retValue << endl;
return retValue;
}
int get_Item_Immune_Value(string inputString)
{
string arImmune[] = {"PARA","CURSE","STUN","SLEEP","SLOW","POISON","TERROR"};
int retValue = 0;
string* arInputString = StringSplit(inputString, "|"); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ܾ<DCBE><EEBAB0> <20>ɰ<EFBFBD> <20>迭.
for(int i =0;i<sizeof(arImmune)/sizeof(arImmune[0]);i++) {
string tempString = arImmune[i];
for (int j=0; j<30 ; j++) //<2F>ִ<EFBFBD> 30<33><30> <20>ܾ<EFBFBD><DCBE><EFBFBD><EFBFBD><EFBFBD>. (<28>ϵ<EFBFBD><CFB5>ڵ<EFBFBD>)
{
string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //<2F><>ġ<EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD> Ȯ<><C8AE>.
retValue = retValue + pow((float)2,(float)i);
}
if(tempString2.compare("") == 0)
break;
}
}
delete []arInputString;
//cout << "Immune : " << immuneStr << " -> " << retValue << endl;
return retValue;
}
int get_Item_LimitType_Value(string inputString)
{
string arLimitType[] = {"LIMIT_NONE", "LEVEL", "STR", "DEX", "INT", "CON", "PC_BANG", "REAL_TIME", "REAL_TIME_FIRST_USE", "TIMER_BASED_ON_WEAR"};
int retInt = -1;
//cout << "LimitType : " << limitTypeStr << " -> ";
for (int j=0;j<sizeof(arLimitType)/sizeof(arLimitType[0]);j++) {
string tempString = arLimitType[j];
string tempInputString = trim(inputString);
if (tempInputString.compare(tempString)==0)
{
//cout << j << " ";
retInt = j;
break;
}
}
//cout << endl;
return retInt;
}
int get_Item_ApplyType_Value(string inputString)
{
string arApplyType[] = {"APPLY_NONE", "APPLY_MAX_HP", "APPLY_MAX_SP", "APPLY_CON", "APPLY_INT", "APPLY_STR", "APPLY_DEX", "APPLY_ATT_SPEED",
"APPLY_MOV_SPEED", "APPLY_CAST_SPEED", "APPLY_HP_REGEN", "APPLY_SP_REGEN", "APPLY_POISON_PCT", "APPLY_STUN_PCT",
"APPLY_SLOW_PCT", "APPLY_CRITICAL_PCT", "APPLY_PENETRATE_PCT", "APPLY_ATTBONUS_HUMAN", "APPLY_ATTBONUS_ANIMAL",
"APPLY_ATTBONUS_ORC", "APPLY_ATTBONUS_MILGYO", "APPLY_ATTBONUS_UNDEAD", "APPLY_ATTBONUS_DEVIL", "APPLY_STEAL_HP",
"APPLY_STEAL_SP", "APPLY_MANA_BURN_PCT", "APPLY_DAMAGE_SP_RECOVER", "APPLY_BLOCK", "APPLY_DODGE", "APPLY_RESIST_SWORD",
"APPLY_RESIST_TWOHAND", "APPLY_RESIST_DAGGER", "APPLY_RESIST_BELL", "APPLY_RESIST_FAN", "APPLY_RESIST_BOW", "APPLY_RESIST_FIRE",
"APPLY_RESIST_ELEC", "APPLY_RESIST_MAGIC", "APPLY_RESIST_WIND", "APPLY_REFLECT_MELEE", "APPLY_REFLECT_CURSE", "APPLY_POISON_REDUCE",
"APPLY_KILL_SP_RECOVER", "APPLY_EXP_DOUBLE_BONUS", "APPLY_GOLD_DOUBLE_BONUS", "APPLY_ITEM_DROP_BONUS", "APPLY_POTION_BONUS",
"APPLY_KILL_HP_RECOVER", "APPLY_IMMUNE_STUN", "APPLY_IMMUNE_SLOW", "APPLY_IMMUNE_FALL", "APPLY_SKILL", "APPLY_BOW_DISTANCE",
"APPLY_ATT_GRADE_BONUS", "APPLY_DEF_GRADE_BONUS", "APPLY_MAGIC_ATT_GRADE", "APPLY_MAGIC_DEF_GRADE", "APPLY_CURSE_PCT",
"APPLY_MAX_STAMINA", "APPLY_ATTBONUS_WARRIOR", "APPLY_ATTBONUS_ASSASSIN", "APPLY_ATTBONUS_SURA", "APPLY_ATTBONUS_SHAMAN",
"APPLY_ATTBONUS_MONSTER", "APPLY_MALL_ATTBONUS", "APPLY_MALL_DEFBONUS", "APPLY_MALL_EXPBONUS", "APPLY_MALL_ITEMBONUS",
"APPLY_MALL_GOLDBONUS", "APPLY_MAX_HP_PCT", "APPLY_MAX_SP_PCT", "APPLY_SKILL_DAMAGE_BONUS", "APPLY_NORMAL_HIT_DAMAGE_BONUS",
"APPLY_SKILL_DEFEND_BONUS", "APPLY_NORMAL_HIT_DEFEND_BONUS", "APPLY_PC_BANG_EXP_BONUS", "APPLY_PC_BANG_DROP_BONUS",
"APPLY_EXTRACT_HP_PCT", "APPLY_RESIST_WARRIOR", "APPLY_RESIST_ASSASSIN", "APPLY_RESIST_SURA", "APPLY_RESIST_SHAMAN",
"APPLY_ENERGY", "APPLY_DEF_GRADE", "APPLY_COSTUME_ATTR_BONUS", "APPLY_MAGIC_ATTBONUS_PER", "APPLY_MELEE_MAGIC_ATTBONUS_PER",
"APPLY_RESIST_ICE", "APPLY_RESIST_EARTH", "APPLY_RESIST_DARK", "APPLY_ANTI_CRITICAL_PCT", "APPLY_ANTI_PENETRATE_PCT",
};
int retInt = -1;
//cout << "ApplyType : " << applyTypeStr << " -> ";
for (int j=0;j<sizeof(arApplyType)/sizeof(arApplyType[0]);j++) {
string tempString = arApplyType[j];
string tempInputString = trim(inputString);
if (tempInputString.compare(tempString)==0)
{
//cout << j << " ";
retInt = j;
break;
}
}
//cout << endl;
return retInt;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><20>д´<D0B4>.
int get_Mob_Rank_Value(string inputString)
{
string arRank[] = {"PAWN", "S_PAWN", "KNIGHT", "S_KNIGHT", "BOSS", "KING"};
int retInt = -1;
//cout << "Rank : " << rankStr << " -> ";
for (int j=0;j<sizeof(arRank)/sizeof(arRank[0]);j++) {
string tempString = arRank[j];
string tempInputString = trim(inputString);
if (tempInputString.compare(tempString)==0)
{
//cout << j << " ";
retInt = j;
break;
}
}
//cout << endl;
return retInt;
}
int get_Mob_Type_Value(string inputString)
{
string arType[] = { "MONSTER", "NPC", "STONE", "WARP", "DOOR", "BUILDING", "PC", "POLYMORPH_PC", "HORSE", "GOTO"};
int retInt = -1;
//cout << "Type : " << typeStr << " -> ";
for (int j=0;j<sizeof(arType)/sizeof(arType[0]);j++) {
string tempString = arType[j];
string tempInputString = trim(inputString);
if (tempInputString.compare(tempString)==0)
{
//cout << j << " ";
retInt = j;
break;
}
}
//cout << endl;
return retInt;
}
int get_Mob_BattleType_Value(string inputString)
{
string arBattleType[] = { "MELEE", "RANGE", "MAGIC", "SPECIAL", "POWER", "TANKER", "SUPER_POWER", "SUPER_TANKER"};
int retInt = -1;
//cout << "Battle Type : " << battleTypeStr << " -> ";
for (int j=0;j<sizeof(arBattleType)/sizeof(arBattleType[0]);j++) {
string tempString = arBattleType[j];
string tempInputString = trim(inputString);
if (tempInputString.compare(tempString)==0)
{
//cout << j << " ";
retInt = j;
break;
}
}
//cout << endl;
return retInt;
}
int get_Mob_Size_Value(string inputString)
{
string arSize[] = { "SAMLL", "MEDIUM", "BIG"};
int retInt = 0;
//cout << "Size : " << sizeStr << " -> ";
for (int j=0;j<sizeof(arSize)/sizeof(arSize[0]);j++) {
string tempString = arSize[j];
string tempInputString = trim(inputString);
if (tempInputString.compare(tempString)==0)
{
//cout << j << " ";
retInt = j + 1;
break;
}
}
//cout << endl;
return retInt;
}
int get_Mob_AIFlag_Value(string inputString)
{
string arAIFlag[] = {"AGGR","NOMOVE","COWARD","NOATTSHINSU","NOATTCHUNJO","NOATTJINNO","ATTMOB","BERSERK","STONESKIN","GODSPEED","DEATHBLOW","REVIVE"};
int retValue = 0;
string* arInputString = StringSplit(inputString, ","); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ܾ<DCBE><EEBAB0> <20>ɰ<EFBFBD> <20>迭.
for(int i =0;i<sizeof(arAIFlag)/sizeof(arAIFlag[0]);i++) {
string tempString = arAIFlag[i];
for (int j=0; j<30 ; j++) //<2F>ִ<EFBFBD> 30<33><30> <20>ܾ<EFBFBD><DCBE><EFBFBD><EFBFBD><EFBFBD>. (<28>ϵ<EFBFBD><CFB5>ڵ<EFBFBD>)
{
string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //<2F><>ġ<EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD> Ȯ<><C8AE>.
retValue = retValue + pow((float)2,(float)i);
}
if(tempString2.compare("") == 0)
break;
}
}
delete []arInputString;
//cout << "AIFlag : " << aiFlagStr << " -> " << retValue << endl;
return retValue;
}
int get_Mob_RaceFlag_Value(string inputString)
{
string arRaceFlag[] = {"ANIMAL","UNDEAD","DEVIL","HUMAN","ORC","MILGYO","INSECT","FIRE","ICE","DESERT","TREE",
"ATT_ELEC","ATT_FIRE","ATT_ICE","ATT_WIND","ATT_EARTH","ATT_DARK"};
int retValue = 0;
string* arInputString = StringSplit(inputString, ","); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ܾ<DCBE><EEBAB0> <20>ɰ<EFBFBD> <20>迭.
for(int i =0;i<sizeof(arRaceFlag)/sizeof(arRaceFlag[0]);i++) {
string tempString = arRaceFlag[i];
for (int j=0; j<30 ; j++) //<2F>ִ<EFBFBD> 30<33><30> <20>ܾ<EFBFBD><DCBE><EFBFBD><EFBFBD><EFBFBD>. (<28>ϵ<EFBFBD><CFB5>ڵ<EFBFBD>)
{
string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //<2F><>ġ<EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD> Ȯ<><C8AE>.
retValue = retValue + pow((float)2,(float)i);
}
if(tempString2.compare("") == 0)
break;
}
}
delete []arInputString;
//cout << "Race Flag : " << raceFlagStr << " -> " << retValue << endl;
return retValue;
}
int get_Mob_ImmuneFlag_Value(string inputString)
{
string arImmuneFlag[] = {"STUN","SLOW","FALL","CURSE","POISON","TERROR", "REFLECT"};
int retValue = 0;
string* arInputString = StringSplit(inputString, ","); //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ܾ<DCBE><EEBAB0> <20>ɰ<EFBFBD> <20>迭.
for(int i =0;i<sizeof(arImmuneFlag)/sizeof(arImmuneFlag[0]);i++) {
string tempString = arImmuneFlag[i];
for (int j=0; j<30 ; j++) //<2F>ִ<EFBFBD> 30<33><30> <20>ܾ<EFBFBD><DCBE><EFBFBD><EFBFBD><EFBFBD>. (<28>ϵ<EFBFBD><CFB5>ڵ<EFBFBD>)
{
string tempString2 = arInputString[j];
if (tempString2.compare(tempString)==0) { //<2F><>ġ<EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD> Ȯ<><C8AE>.
retValue = retValue + pow((float)2,(float)i);
}
if(tempString2.compare("") == 0)
break;
}
}
delete []arInputString;
//cout << "Immune Flag : " << immuneFlagStr << " -> " << retValue << endl;
return retValue;
}
#ifndef __DUMP_PROTO__
//<2F><> <20><><EFBFBD>̺<EFBFBD><CCBA><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
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. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD> <20>־<EFBFBD><D6BE>ֱ<EFBFBD>.
map<int,const char*>::iterator it;
it = nameMap.find(mobTable->dwVnum);
if (it != nameMap.end()) {
const char * localeName = it->second;
strlcpy(mobTable->szLocaleName, localeName, sizeof (mobTable->szLocaleName));
} else {
strlcpy(mobTable->szLocaleName, mobTable->szName, sizeof (mobTable->szLocaleName));
}
//RANK
int rankValue = get_Mob_Rank_Value(csvTable.AsStringByIndex(col++));
mobTable->bRank = rankValue;
//TYPE
int typeValue = get_Mob_Type_Value(csvTable.AsStringByIndex(col++));
mobTable->bType = typeValue;
//BATTLE_TYPE
int battleTypeValue = get_Mob_BattleType_Value(csvTable.AsStringByIndex(col++));
mobTable->bBattleType = battleTypeValue;
str_to_number(mobTable->bLevel, csvTable.AsStringByIndex(col++));
//SIZE
int sizeValue = get_Mob_Size_Value(csvTable.AsStringByIndex(col++));
mobTable->bSize = sizeValue;
//AI_FLAG
int aiFlagValue = get_Mob_AIFlag_Value(csvTable.AsStringByIndex(col++));
mobTable->dwAIFlag = aiFlagValue;
//mount_capacity;
col++;
//RACE_FLAG
int raceFlagValue = get_Mob_RaceFlag_Value(csvTable.AsStringByIndex(col++));
mobTable->dwRaceFlag = raceFlagValue;
//IMMUNE_FLAG
int immuneFlagValue = get_Mob_ImmuneFlag_Value(csvTable.AsStringByIndex(col++));
mobTable->dwImmuneFlag = immuneFlagValue;
str_to_number(mobTable->bEmpire, csvTable.AsStringByIndex(col++)); //col = 11
strlcpy(mobTable->szFolder, csvTable.AsStringByIndex(col++), sizeof(mobTable->szFolder));
str_to_number(mobTable->bOnClickType, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->bStr, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->bDex, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->bCon, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->bInt, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->dwDamageRange[0], csvTable.AsStringByIndex(col++));
str_to_number(mobTable->dwDamageRange[1], csvTable.AsStringByIndex(col++));
str_to_number(mobTable->dwMaxHP, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->bRegenCycle, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->bRegenPercent, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->dwGoldMin, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->dwGoldMax, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->dwExp, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->wDef, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->sAttackSpeed, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->sMovingSpeed, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->bAggresiveHPPct, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->wAggressiveSight, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->wAttackRange, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->dwDropItemVnum, csvTable.AsStringByIndex(col++)); //32
str_to_number(mobTable->dwResurrectionVnum, csvTable.AsStringByIndex(col++));
for (int i = 0; i < MOB_ENCHANTS_MAX_NUM; ++i)
str_to_number(mobTable->cEnchants[i], csvTable.AsStringByIndex(col++));
for (int i = 0; i < MOB_RESISTS_MAX_NUM; ++i)
str_to_number(mobTable->cResists[i], csvTable.AsStringByIndex(col++));
str_to_number(mobTable->fDamMultiply, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->dwSummonVnum, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->dwDrainSP, csvTable.AsStringByIndex(col++));
//Mob_Color
++col;
str_to_number(mobTable->dwPolymorphItemVnum, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->Skills[0].bLevel, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->Skills[0].dwVnum, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->Skills[1].bLevel, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->Skills[1].dwVnum, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->Skills[2].bLevel, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->Skills[2].dwVnum, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->Skills[3].bLevel, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->Skills[3].dwVnum, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->Skills[4].bLevel, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->Skills[4].dwVnum, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->bBerserkPoint, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->bStoneSkinPoint, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->bGodSpeedPoint, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->bDeathBlowPoint, csvTable.AsStringByIndex(col++));
str_to_number(mobTable->bRevivePoint, csvTable.AsStringByIndex(col++));
sys_log(0, "MOB #%-5d %-24s level: %-3u rank: %u empire: %d", mobTable->dwVnum, mobTable->szLocaleName, mobTable->bLevel, mobTable->bRank, mobTable->bEmpire);
return true;
}
bool Set_Proto_Item_Table(TItemTable *itemTable, cCsvTable &csvTable,std::map<int,const char*> &nameMap)
{
int col = 0;
int dataArray[33];
for (int i=0; i<sizeof(dataArray)/sizeof(dataArray[0]);i++) {
int validCheck = 0;
if (i==2) {
dataArray[i] = get_Item_Type_Value(csvTable.AsStringByIndex(col));
validCheck = dataArray[i];
} else if (i==3) {
dataArray[i] = get_Item_SubType_Value(dataArray[i-1], csvTable.AsStringByIndex(col));
validCheck = dataArray[i];
} else if (i==5) {
dataArray[i] = get_Item_AntiFlag_Value(csvTable.AsStringByIndex(col));
validCheck = dataArray[i];
} else if (i==6) {
dataArray[i] = get_Item_Flag_Value(csvTable.AsStringByIndex(col));
validCheck = dataArray[i];
} else if (i==7) {
dataArray[i] = get_Item_WearFlag_Value(csvTable.AsStringByIndex(col));
validCheck = dataArray[i];
} else if (i==8) {
dataArray[i] = get_Item_Immune_Value(csvTable.AsStringByIndex(col));
validCheck = dataArray[i];
} else if (i==14) {
dataArray[i] = get_Item_LimitType_Value(csvTable.AsStringByIndex(col));
validCheck = dataArray[i];
} else if (i==16) {
dataArray[i] = get_Item_LimitType_Value(csvTable.AsStringByIndex(col));
validCheck = dataArray[i];
} else if (i==18) {
dataArray[i] = get_Item_ApplyType_Value(csvTable.AsStringByIndex(col));
validCheck = dataArray[i];
} else if (i==20) {
dataArray[i] = get_Item_ApplyType_Value(csvTable.AsStringByIndex(col));
validCheck = dataArray[i];
} else if (i==22) {
dataArray[i] = get_Item_ApplyType_Value(csvTable.AsStringByIndex(col));
validCheck = dataArray[i];
} else {
str_to_number(dataArray[i], csvTable.AsStringByIndex(col));
}
if (validCheck == -1)
{
std::ostringstream dataStream;
for (int j = 0; j < i; ++j)
dataStream << dataArray[j] << ",";
//fprintf(stderr, "ItemProto Reading Failed : Invalid value.\n");
sys_err("ItemProto Reading Failed : Invalid value. (index: %d, col: %d, value: %s)", i, col, csvTable.AsStringByIndex(col));
sys_err("\t%d ~ %d Values: %s", 0, i, dataStream.str().c_str());
exit(0);
}
col = col + 1;
}
// vnum <20><> vnum range <20>б<EFBFBD>.
{
std::string s(csvTable.AsStringByIndex(0));
int pos = s.find("~");
// vnum <20>ʵ忡 '~'<27><> <20><><EFBFBD>ٸ<EFBFBD> <20>н<EFBFBD>
if (std::string::npos == pos)
{
itemTable->dwVnum = dataArray[0];
itemTable->dwVnumRange = 0;
}
else
{
std::string s_start_vnum (s.substr(0, pos));
std::string s_end_vnum (s.substr(pos +1 ));
int start_vnum = atoi(s_start_vnum.c_str());
int end_vnum = atoi(s_end_vnum.c_str());
if (0 == start_vnum || (0 != end_vnum && end_vnum < start_vnum))
{
sys_err ("INVALID VNUM %s", s.c_str());
return false;
}
itemTable->dwVnum = start_vnum;
itemTable->dwVnumRange = end_vnum - start_vnum;
}
}
strlcpy(itemTable->szName, csvTable.AsStringByIndex(1), sizeof(itemTable->szName));
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD> <20>־<EFBFBD><D6BE>ֱ<EFBFBD>.
map<int,const char*>::iterator it;
it = nameMap.find(itemTable->dwVnum);
if (it != nameMap.end()) {
const char * localeName = it->second;
strlcpy(itemTable->szLocaleName, localeName, sizeof (itemTable->szLocaleName));
} else {
strlcpy(itemTable->szLocaleName, itemTable->szName, sizeof (itemTable->szLocaleName));
}
itemTable->bType = dataArray[2];
itemTable->bSubType = dataArray[3];
itemTable->bSize = dataArray[4];
itemTable->dwAntiFlags = dataArray[5];
itemTable->dwFlags = dataArray[6];
itemTable->dwWearFlags = dataArray[7];
itemTable->dwImmuneFlag = dataArray[8];
itemTable->dwGold = dataArray[9];
itemTable->dwShopBuyPrice = dataArray[10];
itemTable->dwRefinedVnum = dataArray[11];
itemTable->wRefineSet = dataArray[12];
itemTable->bAlterToMagicItemPct = dataArray[13];
itemTable->cLimitRealTimeFirstUseIndex = -1;
itemTable->cLimitTimerBasedOnWearIndex = -1;
int i;
for (i = 0; i < ITEM_LIMIT_MAX_NUM; ++i)
{
itemTable->aLimits[i].bType = dataArray[14+i*2];
itemTable->aLimits[i].lValue = dataArray[15+i*2];
if (LIMIT_REAL_TIME_START_FIRST_USE == itemTable->aLimits[i].bType)
itemTable->cLimitRealTimeFirstUseIndex = (char)i;
if (LIMIT_TIMER_BASED_ON_WEAR == itemTable->aLimits[i].bType)
itemTable->cLimitTimerBasedOnWearIndex = (char)i;
}
for (i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
{
itemTable->aApplies[i].bType = dataArray[18+i*2];
itemTable->aApplies[i].lValue = dataArray[19+i*2];
}
for (i = 0; i < ITEM_VALUES_MAX_NUM; ++i)
itemTable->alValues[i] = dataArray[24+i];
//column for 'Specular'
itemTable->bGainSocketPct = dataArray[31];
itemTable->sAddonType = dataArray[32];
//test
str_to_number(itemTable->bWeight, "0");
return true;
}
#endif

36
db/src/ProtoReader.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef __Item_CSV_READER_H__
#define __Item_CSV_READER_H__
#include <iostream>
#include <map>
#include "CsvReader.h"
//csv <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>о<EFBFBD><D0BE>ͼ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>̺<EFBFBD><CCBA><EFBFBD> <20>־<EFBFBD><D6BE>ش<EFBFBD>.
void putItemIntoTable(); //(<28><><EFBFBD>̺<EFBFBD>, <20>׽<EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD><EFBFBD>)
int get_Item_Type_Value(std::string inputString);
int get_Item_SubType_Value(int type_value, std::string inputString);
int get_Item_AntiFlag_Value(std::string inputString);
int get_Item_Flag_Value(std::string inputString);
int get_Item_WearFlag_Value(std::string inputString);
int get_Item_Immune_Value(std::string inputString);
int get_Item_LimitType_Value(std::string inputString);
int get_Item_ApplyType_Value(std::string inputString);
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD>.
int get_Mob_Rank_Value(std::string inputString);
int get_Mob_Type_Value(std::string inputString);
int get_Mob_BattleType_Value(std::string inputString);
int get_Mob_Size_Value(std::string inputString);
int get_Mob_AIFlag_Value(std::string inputString);
int get_Mob_RaceFlag_Value(std::string inputString);
int get_Mob_ImmuneFlag_Value(std::string inputString);
//
bool Set_Proto_Mob_Table(TMobTable *mobTable, cCsvTable &csvTable, std::map<int,const char*> &nameMap);
bool Set_Proto_Item_Table(TItemTable *itemTable, cCsvTable &csvTable,std::map<int,const char*> &nameMap);
#endif

39
db/src/QID.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef __INC_METIN_II_DB_QID_H__
#define __INC_METIN_II_DB_QID_H__
/**
* @version 05/06/10 Bang2ni - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>߰<EFBFBD>(QID_ITEMPRICE_XXX)
*/
enum QID
{
QID_PLAYER, // 0
QID_ITEM, // 1
QID_QUEST, // 2
QID_AFFECT, // 3
QID_LOGIN, // 4
QID_SAFEBOX_LOAD, // 5
QID_SAFEBOX_CHANGE_SIZE, // 6
QID_SAFEBOX_CHANGE_PASSWORD, // 7
QID_SAFEBOX_CHANGE_PASSWORD_SECOND, // 8
QID_SAFEBOX_SAVE, // 9
QID_ITEM_SAVE, // 10
QID_ITEM_DESTROY, // 11
QID_QUEST_SAVE, // 12
QID_PLAYER_SAVE, // 13
QID_HIGHSCORE_REGISTER, // 14
QID_PLAYER_DELETE, // 15
QID_LOGIN_BY_KEY, // 16
QID_PLAYER_INDEX_CREATE, // 17
QID_ITEM_AWARD_LOAD, // 18
QID_ITEM_AWARD_TAKEN, // 19
QID_GUILD_RANKING, // 20
// MYSHOP_PRICE_LIST
QID_ITEMPRICE_SAVE, ///< 21, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
QID_ITEMPRICE_DESTROY, ///< 22, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
QID_ITEMPRICE_LOAD_FOR_UPDATE, ///< 23, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD> <20><><EFBFBD><EFBFBD>
QID_ITEMPRICE_LOAD, ///< 24, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD> <20><><EFBFBD><EFBFBD>
// END_OF_MYSHOP_PRICE_LIST
};
#endif

130
db/src/grid.cpp Normal file
View File

@ -0,0 +1,130 @@
#include <string.h>
#include <stdio.h>
#include "../../libthecore/include/memcpy.h"
#include "../../common/stl.h"
#include "grid.h"
CGrid::CGrid(int w, int h) : m_iWidth(w), m_iHeight(h)
{
m_pGrid = new char[m_iWidth * m_iHeight];
memset(m_pGrid, 0, sizeof(char) * m_iWidth * m_iHeight);
}
CGrid::CGrid(CGrid * pkGrid, int w, int h) : m_iWidth(w), m_iHeight(h)
{
m_pGrid = new char[m_iWidth * m_iHeight];
int iSize = std::MIN(w * h, pkGrid->m_iWidth * pkGrid->m_iHeight);
thecore_memcpy(m_pGrid, pkGrid->m_pGrid, sizeof(char) * iSize);
}
CGrid::~CGrid()
{
delete [] m_pGrid;
}
void CGrid::Clear()
{
memset(m_pGrid, 0, sizeof(char) * m_iWidth * m_iHeight);
}
int CGrid::FindBlank(int w, int h)
{
// ũ<><20><> ũ<>ٸ<EFBFBD> Ȯ<><C8AE><EFBFBD><EFBFBD> <20>ʿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>׳<EFBFBD> <20><><EFBFBD><EFBFBD>
if (w > m_iWidth || h > m_iHeight)
return -1;
int iRow;
for (iRow = 0; iRow < m_iHeight; ++iRow)
{
for (int iCol = 0; iCol < m_iWidth; ++iCol)
{
int iIndex = iRow * m_iWidth + iCol;
if (IsEmpty(iIndex, w, h))
return iIndex;
}
}
return -1;
}
bool CGrid::Put(int iPos, int w, int h)
{
if (!IsEmpty(iPos, w, h))
return false;
for (int y = 0; y < h; ++y)
{
int iStart = iPos + (y * m_iWidth);
m_pGrid[iStart] = true;
int x = 1;
while (x < w)
m_pGrid[iStart + x++] = true;
}
return true;
}
void CGrid::Get(int iPos, int w, int h)
{
if (iPos >= m_iWidth * m_iHeight)
return;
for (int y = 0; y < h; ++y)
{
int iStart = iPos + (y * m_iWidth);
m_pGrid[iStart] = false;
int x = 1;
while (x < w)
m_pGrid[iStart + x++] = false;
}
}
bool CGrid::IsEmpty(int iPos, int w, int h)
{
int iRow = iPos / m_iWidth;
// Grid <20><><EFBFBD><EFBFBD><EFBFBD>ΰ<EFBFBD><CEB0><EFBFBD> <20><><EFBFBD><EFBFBD> <20>˻<EFBFBD>
if (iRow + h > m_iHeight)
return false;
if (iPos + w > iRow * m_iWidth + m_iWidth)
return false;
for (int y = 0; y < h; ++y)
{
int iStart = iPos + (y * m_iWidth);
if (m_pGrid[iStart])
return false;
int x = 1;
while (x < w)
if (m_pGrid[iStart + x++])
return false;
}
return true;
}
void CGrid::Print()
{
printf("Grid %p\n", this);
for (int y = 0; y < m_iHeight; ++y)
{
for (int x = 0; x < m_iWidth; ++x)
printf("%d", m_pGrid[y * m_iWidth + x]);
printf("\n");
}
}
unsigned int CGrid::GetSize()
{
return m_iWidth * m_iHeight;
}

27
db/src/grid.h Normal file
View File

@ -0,0 +1,27 @@
// vim: ts=8 sw=4
#ifndef __INC_METIN_II_GRID_H__
#define __INC_METIN_II_GRID_H__
class CGrid
{
public:
CGrid(int w, int h);
CGrid(CGrid * pkGrid, int w, int h);
~CGrid();
void Clear();
int FindBlank(int w, int h);
bool IsEmpty(int iPos, int w, int h);
bool Put(int iPos, int w, int h);
void Get(int iPos, int w, int h);
void Print();
unsigned int GetSize();
protected:
int m_iWidth;
int m_iHeight;
char * m_pGrid;
};
#endif

20
db/src/stdafx.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef __INC_METiN_II_DBSERV_STDAFX_H__
#define __INC_METiN_II_DBSERV_STDAFX_H__
#include "../../libthecore/include/stdafx.h"
#ifndef __WIN32__
#include <semaphore.h>
#else
#define isdigit iswdigit
#define isspace iswspace
#endif
#include "../../common/length.h"
#include "../../common/tables.h"
#include "../../common/singleton.h"
#include "../../common/utils.h"
#include "../../common/stl.h"
#include "../../common/service.h"
#endif

22
db/src/version.cpp Normal file
View File

@ -0,0 +1,22 @@
#include <stdio.h>
#include <stdlib.h>
void WriteVersion()
{
#ifndef __WIN32__
FILE* fp(fopen("VERSION.txt", "w"));
if (NULL != fp)
{
fprintf(fp, "game perforce revision: %s\n", __P4_VERSION__);
fprintf(fp, "%s@%s:%s\n", __USER__, __HOSTNAME__, __PWD__);
fclose(fp);
}
else
{
fprintf(stderr, "cannot open VERSION.txt\n");
exit(0);
}
#endif
}