811 lines
31 KiB
C++
811 lines
31 KiB
C++
|
|
#include <atlcomtime.h>
|
|
|
|
#include <mmo/ArcadiaServer.h>
|
|
#include <toolkit/XConsole.h>
|
|
#include <logging/FileLog.h>
|
|
|
|
#include "ContentLoader.h"
|
|
#include "GameDBUtil.h"
|
|
#include "DB_Commands.h"
|
|
#include "AuctionManager.h"
|
|
#include "StructSummon.h"
|
|
#include "StructPet.h"
|
|
#include "StructSkill.h"
|
|
#include "DBPerformanceTracker.h"
|
|
#include "ADOConnection.h"
|
|
|
|
|
|
struct AuctionLoader::dbAuction : public CADORecordBinding
|
|
{
|
|
AuctionUID auction_uid;
|
|
ItemUID item_uid;
|
|
PlayerUID seller_uid;
|
|
wchar_t seller_name[31];
|
|
bool is_secroute_only;
|
|
DBTIMESTAMP end_time;
|
|
__int64 instant_purchase_price;
|
|
__int64 registration_tax;
|
|
char bidder_list[1152];
|
|
__int64 highest_bidding_price;
|
|
PlayerUID highest_bidder_uid;
|
|
wchar_t highest_bidder_name[31];
|
|
|
|
BEGIN_ADO_BINDING(dbAuction)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(1, adInteger, auction_uid, sizeof( auction_uid ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(2, adBigInt, item_uid, sizeof( item_uid ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(3, adInteger, seller_uid, sizeof( seller_uid ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(4, adVarWChar, seller_name, _countof( seller_name ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(5, adBoolean, is_secroute_only, sizeof( is_secroute_only ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(6, adDBTimeStamp, end_time, sizeof( end_time ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(7, adBigInt, instant_purchase_price, sizeof( instant_purchase_price ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(8, adBigInt, registration_tax, sizeof( registration_tax ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(9, adVarChar, bidder_list, _countof( bidder_list ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(10, adBigInt, highest_bidding_price, sizeof( highest_bidding_price ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(11, adInteger, highest_bidder_uid, sizeof( highest_bidder_uid ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(12, adVarWChar, highest_bidder_name, _countof( highest_bidder_name ), FALSE)
|
|
END_ADO_BINDING()
|
|
};
|
|
|
|
struct AuctionLoader::dbItemKeeping : public CADORecordBinding
|
|
{
|
|
ItemKeepingUID keeping_uid;
|
|
ItemUID item_uid;
|
|
PlayerUID owner_uid;
|
|
DBTIMESTAMP expiration_time;
|
|
int keeping_type;
|
|
AuctionUID related_auction_id;
|
|
ItemBase::ItemCode related_item_code;
|
|
int related_item_enhance;
|
|
int related_item_level;
|
|
|
|
BEGIN_ADO_BINDING(dbItemKeeping)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(1, adInteger, keeping_uid, sizeof( keeping_uid ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(2, adBigInt, item_uid, sizeof( item_uid ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(3, adInteger, owner_uid, sizeof( owner_uid ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(4, adDBTimeStamp, expiration_time, sizeof( expiration_time ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(5, adInteger, keeping_type, sizeof( keeping_type ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(6, adInteger, related_auction_id, sizeof( related_auction_id ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(7, adInteger, related_item_code, sizeof( related_item_code ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(8, adInteger, related_item_enhance, sizeof( related_item_enhance ), FALSE)
|
|
ADO_VARIABLE_LENGTH_ENTRY4(9, adInteger, related_item_level, sizeof( related_item_level ), FALSE)
|
|
END_ADO_BINDING()
|
|
};
|
|
|
|
bool AuctionLoader::onProcess( int nThreadNum )
|
|
{
|
|
DBPerformanceTrackHelper helper;
|
|
try
|
|
{
|
|
_ConnectionPtr ConnPtr = NULL;
|
|
InitUserDbConnection( ConnPtr );
|
|
// 느린 쿼리 타임아웃 조정
|
|
ConnPtr->CommandTimeout = 5*60; // 5분
|
|
|
|
try
|
|
{
|
|
helper.start();
|
|
loadAuctionAndKeepingSummonList( ConnPtr );
|
|
helper.end( "dbo.smp_read_auction_and_keeping_summon_list" );
|
|
}
|
|
catch( _com_error &e )
|
|
{
|
|
helper.end( "dbo.smp_read_auction_and_keeping_summon_list" );
|
|
LogDBError( e, "AuctionLoader", "dbo.smp_read_auction_and_keeping_summon_list" );
|
|
throw;
|
|
}
|
|
|
|
try
|
|
{
|
|
helper.start();
|
|
loadAuctionAndKeepingPetList( ConnPtr );
|
|
helper.end( "dbo.smp_read_auction_and_keeping_pet_list" );
|
|
}
|
|
catch( _com_error &e )
|
|
{
|
|
helper.end( "dbo.smp_read_auction_and_keeping_pet_list" );
|
|
LogDBError( e, "AuctionLoader", "dbo.smp_read_auction_and_keeping_pet_list" );
|
|
throw;
|
|
}
|
|
|
|
try
|
|
{
|
|
helper.start();
|
|
_loadRandomOptionList( ConnPtr );
|
|
helper.end( "dbo.smp_read_auction_awaken_option_list" );
|
|
}
|
|
catch( _com_error &e )
|
|
{
|
|
helper.end( "dbo.smp_read_auction_awaken_option_list" );
|
|
LogDBError( e, "AuctionLoader", "dbo.smp_read_auction_awaken_option_list" );
|
|
throw;
|
|
}
|
|
|
|
try
|
|
{
|
|
helper.start();
|
|
loadAuctionAndKeepingItem( ConnPtr );
|
|
helper.end( "smp_read_auction_and_keeping_item_list" );
|
|
}
|
|
catch( _com_error &e )
|
|
{
|
|
helper.end( "smp_read_auction_and_keeping_item_list" );
|
|
LogDBError( e, "AuctionLoader", "smp_read_auction_and_keeping_item_list" );
|
|
throw;
|
|
}
|
|
|
|
try
|
|
{
|
|
helper.start();
|
|
loadAuctionInfo( ConnPtr );
|
|
helper.end( "Auction table binding" );
|
|
}
|
|
catch( _com_error &e )
|
|
{
|
|
helper.end( "Auction table binding" );
|
|
LogDBError( e, "AuctionLoader", "Auction table binding" );
|
|
throw;
|
|
}
|
|
|
|
try
|
|
{
|
|
helper.start();
|
|
loadItemKeepingInfo( ConnPtr );
|
|
helper.end( "ItemKeeping table binding" );
|
|
}
|
|
catch( _com_error &e )
|
|
{
|
|
helper.end( "ItemKeeping table binding" );
|
|
LogDBError( e, "AuctionLoader", "ItemKeeping table binding" );
|
|
throw;
|
|
}
|
|
|
|
clearLoadedItem();
|
|
clearLoadedSummonAndPet();
|
|
clearLoadedRandomOption();
|
|
}
|
|
catch( _com_error &e )
|
|
{
|
|
std::string strError = "AuctionLoader RESOURCE DB ERROR : ";
|
|
strError += e.Description();
|
|
throw XException( strError );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AuctionLoader::loadAuctionAndKeepingSummonList( _ConnectionPtr & ConnPtr )
|
|
{
|
|
_CommandPtr cmd;
|
|
if( CreateDBCommand( cmd, ConnPtr ) == false ) throw XException( "loadAuctionAndKeepingSummonList : CreateInstance(command) error" );
|
|
|
|
// 느린 쿼리 타임아웃 조정
|
|
ConnPtr->CommandTimeout = 5*60; // 5분
|
|
cmd->CommandType = adCmdStoredProc;
|
|
cmd->CommandText = _bstr_t( "dbo.smp_read_auction_and_keeping_summon_list" );
|
|
|
|
_RecordsetPtr pRS = cmd->Execute( NULL, NULL, adCmdStoredProc );
|
|
|
|
while( pRS->State != adStateClosed && !pRS->EndOfFile )
|
|
{
|
|
StructSummon *pSummon = StructSummon::AllocSummon( NULL, pRS->Fields->Item["code"]->Value );
|
|
|
|
// _oprint( "ALLOC SUMMON : %08X\n", pSummon );
|
|
pSummon->SetEXP( pRS->Fields->Item["exp"]->Value );
|
|
pSummon->SetLevel( pRS->Fields->Item["lv"]->Value );
|
|
pSummon->SetJobLevel( pRS->Fields->Item["lv"]->Value );
|
|
pSummon->SetMaxReachedLevel( pRS->Fields->Item["max_level"]->Value );
|
|
pSummon->SetSummonSID( pRS->Fields->Item["sid"]->Value );
|
|
pSummon->SetJP( pRS->Fields->Item["jp"]->Value );
|
|
pSummon->SetName( static_cast< _bstr_t >( pRS->Fields->Item["name"]->Value ) );
|
|
pSummon->SetCurrentXY( 0, 0 );
|
|
pSummon->SetPrevJobId( 0, pRS->Fields->Item["prev_id_01"]->Value );
|
|
pSummon->SetPrevJobId( 1, pRS->Fields->Item["prev_id_02"]->Value );
|
|
pSummon->SetPrevJobLevel( 0, pRS->Fields->Item["prev_level_01"]->Value );
|
|
pSummon->SetPrevJobLevel( 1, pRS->Fields->Item["prev_level_02"]->Value );
|
|
pSummon->SetLastDecreasedEXP( pRS->Fields->Item["last_decreased_exp"]->Value.llVal );
|
|
|
|
m_vLoadedSummonList.push_back( pSummon );
|
|
|
|
_loadSummonSkillList( ConnPtr, pSummon );
|
|
|
|
pSummon->CalculateStat();
|
|
|
|
pSummon->SetSP( pRS->Fields->Item["sp"]->Value );
|
|
pSummon->SetHP( pRS->Fields->Item["hp"]->Value );
|
|
pSummon->SetMP( pRS->Fields->Item["mp"]->Value );
|
|
|
|
pRS->MoveNext();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AuctionLoader::loadAuctionAndKeepingPetList( _ConnectionPtr & ConnPtr )
|
|
{
|
|
_CommandPtr cmd;
|
|
if( CreateDBCommand( cmd, ConnPtr ) == false ) throw XException( "loadAuctionAndKeepingPetList : CreateInstance(command) error" );
|
|
|
|
// 느린 쿼리 타임아웃 조정
|
|
ConnPtr->CommandTimeout = 5*60; // 5분
|
|
cmd->CommandType = adCmdStoredProc;
|
|
cmd->CommandText = _bstr_t( "dbo.smp_read_auction_and_keeping_pet_list" );
|
|
|
|
_RecordsetPtr pRS = cmd->Execute( NULL, NULL, adCmdStoredProc );
|
|
|
|
while( pRS->State != adStateClosed && !pRS->EndOfFile )
|
|
{
|
|
StructPet *pPet = StructPet::AllocPet( NULL, pRS->Fields->Item["code"]->Value );
|
|
|
|
pPet->SetPetSID( pRS->Fields->Item["sid"]->Value );
|
|
pPet->SetName( static_cast< _bstr_t >( pRS->Fields->Item["name"]->Value ) );
|
|
pPet->SetNameChanged( pRS->Fields->Item["name_changed"]->Value );
|
|
pPet->GetSkill( StructSkill::SKILL_SHOVELING )->SetRemainCoolTime( pRS->Fields->Item["cool_time_01"]->Value.intVal * 100 );
|
|
|
|
m_vLoadedPetList.push_back( pPet );
|
|
|
|
pRS->MoveNext();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AuctionLoader::_loadSummonSkillList( _ConnectionPtr & ConnPtr, StructSummon * pSummon )
|
|
{
|
|
_CommandPtr cmd;
|
|
if( CreateDBCommand( cmd, ConnPtr ) == false ) throw XException( "_loadSummonSkillList : CreateInstance(command) error" );
|
|
|
|
// 느린 쿼리 타임아웃 조정
|
|
ConnPtr->CommandTimeout = 5*60; // 5분
|
|
cmd->CommandType = adCmdStoredProc;
|
|
cmd->CommandText = _bstr_t( "dbo.smp_read_summon_skill_list" );
|
|
|
|
cmd->Parameters->Append( cmd->CreateParameter( "IN_SID", adInteger, adParamInput, 4, pSummon->GetSummonSID() ) );
|
|
|
|
_RecordsetPtr pRS = cmd->Execute( NULL, NULL, adCmdStoredProc);
|
|
|
|
while( pRS->State != adStateClosed && !pRS->EndOfFile )
|
|
{
|
|
pSummon->SetSkill( pRS->Fields->Item["sid"]->Value,
|
|
pRS->Fields->Item["skill_id"]->Value,
|
|
pRS->Fields->Item["skill_level"]->Value,
|
|
pRS->Fields->Item["cool_time"]->Value );
|
|
pRS->MoveNext();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AuctionLoader::loadAuctionAndKeepingItem( _ConnectionPtr & ConnPtr )
|
|
{
|
|
_RecordsetPtr pRstItemInfo = NULL;
|
|
IADORecordBinding *picRs = NULL; // Interface Pointer declared.
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
pRstItemInfo.CreateInstance( __uuidof(Recordset) );
|
|
|
|
pRstItemInfo->Open( "smp_read_auction_and_keeping_item_list",
|
|
_variant_t((IDispatch *)ConnPtr,true),
|
|
adOpenForwardOnly, adLockReadOnly, adCmdStoredProc );
|
|
|
|
pRstItemInfo->QueryInterface( __uuidof(IADORecordBinding),(LPVOID*)&picRs );
|
|
|
|
StructItem * pItem;
|
|
for( ; pRstItemInfo->State != adStateClosed && !pRstItemInfo->EndOfFile; pRstItemInfo->MoveNext() )
|
|
{
|
|
__int64 id = pRstItemInfo->Fields->Item["sid"]->Value;
|
|
|
|
COleDateTime dtElementalEffectExpire( pRstItemInfo->Fields->Item["elemental_effect_expire_time"]->Value.date );
|
|
|
|
struct tm tmElementalEffectExpire;
|
|
tmElementalEffectExpire.tm_year = dtElementalEffectExpire.GetYear() - 1900;
|
|
tmElementalEffectExpire.tm_mon = dtElementalEffectExpire.GetMonth() - 1;
|
|
tmElementalEffectExpire.tm_mday = dtElementalEffectExpire.GetDay();
|
|
tmElementalEffectExpire.tm_hour = dtElementalEffectExpire.GetHour();
|
|
tmElementalEffectExpire.tm_min = dtElementalEffectExpire.GetMinute();
|
|
tmElementalEffectExpire.tm_sec = dtElementalEffectExpire.GetSecond();
|
|
tmElementalEffectExpire.tm_isdst = -1;
|
|
time_t tElementalEffectExpire = mktime( &tmElementalEffectExpire );
|
|
|
|
pItem = StructItem::AllocItem( pRstItemInfo->Fields->Item["sid"]->Value,
|
|
pRstItemInfo->Fields->Item["code"]->Value,
|
|
pRstItemInfo->Fields->Item["cnt"]->Value.llVal,
|
|
static_cast< ItemInstance::GenerateCode >( static_cast< int >( pRstItemInfo->Fields->Item["gcode"]->Value ) ),
|
|
pRstItemInfo->Fields->Item["level"]->Value,
|
|
pRstItemInfo->Fields->Item["enhance"]->Value,
|
|
pRstItemInfo->Fields->Item["flag"]->Value,
|
|
pRstItemInfo->Fields->Item["socket_0"]->Value,
|
|
pRstItemInfo->Fields->Item["socket_1"]->Value,
|
|
pRstItemInfo->Fields->Item["socket_2"]->Value,
|
|
pRstItemInfo->Fields->Item["socket_3"]->Value,
|
|
pRstItemInfo->Fields->Item["awaken_sid"]->Value,
|
|
pRstItemInfo->Fields->Item["random_option_sid"]->Value,
|
|
std::max( (int) pRstItemInfo->Fields->Item["remain_time"]->Value, 0 ),
|
|
pRstItemInfo->Fields->Item["elemental_effect_type"]->Value.intVal,
|
|
tElementalEffectExpire,
|
|
pRstItemInfo->Fields->Item["elemental_effect_attack_point"]->Value,
|
|
pRstItemInfo->Fields->Item["elemental_effect_magic_point"]->Value,
|
|
pRstItemInfo->Fields->Item["appearance_code"]->Value,
|
|
|
|
// imPakrht - smp_read_auction_and_keeping_item_list 추가 summon_code
|
|
pRstItemInfo->Fields->Item["summon_code"]->Value );
|
|
|
|
pItem->SetCurrentEtherealDurability( pRstItemInfo->Fields->Item["ethereal_durability"]->Value );
|
|
pItem->SetCurrentEndurance( pRstItemInfo->Fields->Item["endurance"]->Value );
|
|
pItem->SetIdx( 0 );
|
|
pItem->SetWearInfo( ItemBase::WEAR_NONE, true );
|
|
pItem->SetAuctionID( pRstItemInfo->Fields->Item["auction_id"]->Value );
|
|
pItem->SetItemKeepingID( pRstItemInfo->Fields->Item["keeping_id"]->Value );
|
|
pItem->TurnOffDbUpdateFlag();
|
|
|
|
if( pItem->IsAwaken() )
|
|
{
|
|
ItemInstance::RANDOM_OPTION kAwakenOption;
|
|
_getRandomOption( pItem->GetAwakenSID(), &kAwakenOption );
|
|
pItem->SetAwakenOption( kAwakenOption );
|
|
}
|
|
|
|
if( pItem->IsIdentified() )
|
|
{
|
|
ItemInstance::RANDOM_OPTION kRandomOption;
|
|
_getRandomOption( pItem->GetIdentifiedSID(), &kRandomOption );
|
|
pItem->SetIdentifiedOption( kRandomOption );
|
|
}
|
|
|
|
// 소환수 카드일 경우 소환수 정보와 아이템 정보를 연결
|
|
if( pItem->IsSummonCard() && pItem->GetInstanceFlag().IsOn( ItemInstance::ITEM_FLAG_SUMMON ) )
|
|
{
|
|
for( std::vector< StructSummon * >::iterator it = m_vLoadedSummonList.begin() ; it != m_vLoadedSummonList.end() ; ++it )
|
|
{
|
|
if( (*it)->GetSummonSID() == pItem->GetSummonSID() )
|
|
{
|
|
StructSummon *pSummon = (*it);
|
|
|
|
m_vLoadedSummonList.erase( it );
|
|
|
|
// 소환수 카드와 아이템의 소환수 코드가 잘못 연결 되 있으면 제대로 연결
|
|
if( pItem->GetSummonCode() != pSummon->GetSummonCode() )
|
|
{
|
|
pItem->SetSummonCode( pSummon->GetSummonCode() );
|
|
pItem->DBQuery( new DB_UpdateItem( pItem ) );
|
|
}
|
|
|
|
pSummon->SetParentCard( pItem );
|
|
pItem->SetSummonStruct( pSummon );
|
|
pItem->SetSummonSID( pSummon->GetSummonSID() );
|
|
|
|
pSummon->SetLoginComplete();
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 펫 아이템 일 경우 펫 정보와 아이템 정보를 연결
|
|
if( pItem->IsPetCage() )
|
|
{
|
|
for( std::vector< StructPet * >::iterator it = m_vLoadedPetList.begin() ; it != m_vLoadedPetList.end() ; ++it )
|
|
{
|
|
if( (*it)->GetPetSID() == pItem->GetPetSID() )
|
|
{
|
|
StructPet *pPet = (*it);
|
|
|
|
m_vLoadedPetList.erase( it );
|
|
|
|
pPet->SetParentCage( pItem );
|
|
pItem->SetPetStruct( pPet );
|
|
|
|
pPet->SetLoginComplete();
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !pushLoadedItem( pItem ) )
|
|
{
|
|
_cprint( "Duplicated loaded auction item detected: sid(%I64d) auction_id(%d) keeping_id(%d)\n", pItem->GetItemUID(), pItem->GetAuctionID(), pItem->GetItemKeepingID() );
|
|
FILELOG( "Duplicated loaded auction item detected: sid(%I64d) auction_id(%d) keeping_id(%d)", pItem->GetItemUID(), pItem->GetAuctionID(), pItem->GetItemKeepingID() );
|
|
AuctionManager::Instance().Push( new DB_UpdateItemAuctionKeepingID( pItem->GetItemUID(), 0, 0 ) );
|
|
StructItem::PendFreeItem( pItem );
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AuctionLoader::_loadRandomOptionList( _ConnectionPtr & ConnPtr )
|
|
{
|
|
_CommandPtr cmd;
|
|
if( CreateDBCommand( cmd, ConnPtr ) == false ) throw XException( "_loadRandomOptionList : CreateInstance(command) error" );
|
|
|
|
// 느린 쿼리 타임아웃 조정
|
|
ConnPtr->CommandTimeout = 5*60; // 5분
|
|
cmd->CommandType = adCmdStoredProc;
|
|
cmd->CommandText = _bstr_t( "dbo.smp_read_auction_random_option_list" );
|
|
|
|
_RecordsetPtr pRS = cmd->Execute( NULL, NULL, adCmdStoredProc );
|
|
|
|
for( ; pRS->State != adStateClosed && !pRS->EndOfFile ; pRS->MoveNext() )
|
|
{
|
|
struct ItemInstance::RANDOM_OPTION RandomOption;
|
|
std::string strBuffer;
|
|
_decimal_variant decBuffer;
|
|
|
|
RandomOption.nSID = pRS->Fields->Item["sid"]->Value;
|
|
RandomOption.nRandomType= pRS->Fields->Item["random_type"]->Value;
|
|
|
|
for( int i = 0; i < ItemInstance::MAX_RANDOM_OPTION_NUMBER; ++i )
|
|
{
|
|
XStringUtil::Format( strBuffer, "type_%02d", i + 1 );
|
|
RandomOption.OptionInfo[i].nType = pRS->Fields->Item[strBuffer.c_str()]->Value;
|
|
|
|
XStringUtil::Format( strBuffer, "value1_%02d", i + 1 );
|
|
*static_cast< DECIMAL * >( &decBuffer ) = pRS->Fields->Item[strBuffer.c_str()]->Value.decVal;
|
|
RandomOption.OptionInfo[i].fValue1.set( decBuffer.getMultipleInteger( 10000 ) );
|
|
|
|
XStringUtil::Format( strBuffer, "value2_%02d", i + 1 );
|
|
*static_cast< DECIMAL * >( &decBuffer ) = pRS->Fields->Item[strBuffer.c_str()]->Value.decVal;
|
|
RandomOption.OptionInfo[i].fValue2.set( decBuffer.getMultipleInteger( 10000 ) );
|
|
}
|
|
|
|
m_vRandomOptionList.push_back( RandomOption );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void AuctionLoader::_getRandomOption( int _SID, ItemInstance::RANDOM_OPTION * _pRandomOption )
|
|
{
|
|
std::vector< ItemInstance::RANDOM_OPTION >::iterator it = m_vRandomOptionList.begin();
|
|
for( ; it != m_vRandomOptionList.end() ; ++it )
|
|
{
|
|
if( _SID == (*it).nSID )
|
|
{
|
|
_pRandomOption->nSID = _SID;
|
|
_pRandomOption->nRandomType = it->nRandomType;
|
|
|
|
for( int nCnt = 0 ; nCnt < ItemInstance::MAX_RANDOM_OPTION_NUMBER ; ++nCnt )
|
|
{
|
|
_pRandomOption->OptionInfo[ nCnt ].nType = (*it).OptionInfo[ nCnt ].nType;
|
|
_pRandomOption->OptionInfo[ nCnt ].fValue1 = (*it).OptionInfo[ nCnt ].fValue1;
|
|
_pRandomOption->OptionInfo[ nCnt ].fValue2 = (*it).OptionInfo[ nCnt ].fValue2;
|
|
}
|
|
|
|
m_vRandomOptionList.erase( it );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool AuctionLoader::loadAuctionInfo( _ConnectionPtr & ConnPtr )
|
|
{
|
|
#ifdef FRAUN_PERFORMANCE_LOG
|
|
DWORD dwTime = GetSafeTickCount();
|
|
#endif
|
|
_RecordsetPtr pRstAuctionInfo = NULL;
|
|
IADORecordBinding *picRs = NULL; // Interface Pointer declared.
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
dbAuction emprs; // C++ Class object
|
|
|
|
pRstAuctionInfo.CreateInstance( __uuidof(Recordset) );
|
|
|
|
pRstAuctionInfo->Open("Auction",
|
|
_variant_t((IDispatch *)ConnPtr,true),
|
|
adOpenForwardOnly, adLockReadOnly, adCmdTable);
|
|
|
|
pRstAuctionInfo->QueryInterface( __uuidof(IADORecordBinding),(LPVOID*)&picRs );
|
|
|
|
picRs->BindToRecordset(&emprs);
|
|
|
|
int nTotalCnt = 0;
|
|
int nLoadCount = 0;
|
|
|
|
while( pRstAuctionInfo->State != adStateClosed && !pRstAuctionInfo->EndOfFile )
|
|
{
|
|
if( onAuctionInfoData( &emprs ) )
|
|
++nLoadCount;
|
|
|
|
hr = pRstAuctionInfo->MoveNext();
|
|
++nTotalCnt;
|
|
}
|
|
|
|
#ifdef FRAUN_PERFORMANCE_LOG
|
|
DWORD loadingTime = GetSafeTickCount() - dwTime;
|
|
_cprint("Total %d/%d AuctionInfo loaded; time taken: %d\n", nLoadCount, nTotalCnt, loadingTime);
|
|
FILELOG("Total %d/%d AuctionInfo loaded; time taken: %d", nLoadCount, nTotalCnt, loadingTime);
|
|
#else
|
|
_cprint( "Total %d/%d AuctionInfo loaded...\n", nLoadCount, nTotalCnt );
|
|
FILELOG( "Total %d/%d AuctionInfo loaded...", nLoadCount, nTotalCnt );
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AuctionLoader::loadItemKeepingInfo( _ConnectionPtr & ConnPtr )
|
|
{
|
|
#ifdef FRAUN_PERFORMANCE_LOG
|
|
DWORD dwTime = GetSafeTickCount();
|
|
#endif
|
|
_RecordsetPtr pRstItemKeepingInfo = NULL;
|
|
IADORecordBinding *picRs = NULL; // Interface Pointer declared.
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
dbItemKeeping emprs; // C++ Class object
|
|
|
|
pRstItemKeepingInfo.CreateInstance( __uuidof(Recordset) );
|
|
|
|
pRstItemKeepingInfo->Open("ItemKeeping",
|
|
_variant_t((IDispatch *)ConnPtr,true),
|
|
adOpenForwardOnly, adLockReadOnly, adCmdTable);
|
|
|
|
pRstItemKeepingInfo->QueryInterface( __uuidof(IADORecordBinding),(LPVOID*)&picRs );
|
|
|
|
picRs->BindToRecordset(&emprs);
|
|
|
|
int nTotalCnt = 0;
|
|
int nLoadCount = 0;
|
|
|
|
while( pRstItemKeepingInfo->State != adStateClosed && !pRstItemKeepingInfo->EndOfFile )
|
|
{
|
|
if( onItemKeepingInfoData( &emprs ) )
|
|
++nLoadCount;
|
|
|
|
hr = pRstItemKeepingInfo->MoveNext();
|
|
++nTotalCnt;
|
|
}
|
|
|
|
#ifdef FRAUN_PERFORMANCE_LOG
|
|
DWORD loadingTime = GetSafeTickCount() - dwTime;
|
|
_cprint("Total %d/%d ItemKeepingInfo loaded; time taken: %d\n", nLoadCount, nTotalCnt, loadingTime);
|
|
FILELOG("Total %d/%d ItemKeepingInfo loaded; time taken: %d", nLoadCount, nTotalCnt, loadingTime);
|
|
#else
|
|
_cprint( "Total %d/%d ItemKeepingInfo loaded...\n", nLoadCount, nTotalCnt );
|
|
FILELOG( "Total %d/%d ItemKeepingInfo loaded...", nLoadCount, nTotalCnt );
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AuctionLoader::onAuctionInfoData( dbAuction * emprs )
|
|
{
|
|
if( !emprs->auction_uid )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 새로 생성될 경매 ID를 현재까지 로딩된 ID보다 커지도록 조정
|
|
UIDManager::Instance().SetMaxUsedUID( "AuctionUID", emprs->auction_uid );
|
|
|
|
StructItem *pItem = popLoadedItem( emprs->item_uid );
|
|
if( !pItem )
|
|
{
|
|
_cprint( "AuctionInfo without related item detected: auction_id(%d) item_id(%I64d) seller_id(%d) registration_tax(%I64d) bidder_list(%s) highest_bidder_id(%d) bidding_price(%I64d)\n",
|
|
emprs->auction_uid, emprs->item_uid, emprs->seller_uid, emprs->registration_tax, emprs->bidder_list, emprs->highest_bidder_uid, emprs->highest_bidding_price );
|
|
FILELOG( "AuctionInfo without related item detected: auction_id(%d) item_id(%I64d) seller_id(%d) registration_tax(%I64d) bidder_list(%s) highest_bidder_id(%d) bidding_price(%I64d)",
|
|
emprs->auction_uid, emprs->item_uid, emprs->seller_uid, emprs->registration_tax, emprs->bidder_list, emprs->highest_bidder_uid, emprs->highest_bidding_price );
|
|
|
|
AuctionManager::Instance().Push( new DB_DeleteAuctionInfo( emprs->auction_uid ) );
|
|
return false;
|
|
}
|
|
|
|
// 아이템 데이터가 경매 데이터와 매치되지 않는 경우
|
|
if( pItem->GetAuctionID() != emprs->auction_uid || pItem->GetItemKeepingID() > 0 )
|
|
{
|
|
_cprint( "AuctionInfo with mis-related item detected: auction_id(%d) item_id(%I64d) keeping_id_on_item(%d) seller_id(%d) registration_tax(%I64d) bidder_list(%s) highest_bidder_id(%d) bidding_price(%I64d)\n",
|
|
emprs->auction_uid, emprs->item_uid, pItem->GetItemKeepingID(), emprs->seller_uid, emprs->registration_tax, emprs->bidder_list, emprs->highest_bidder_uid, emprs->highest_bidding_price );
|
|
FILELOG( "AuctionInfo with mis-related item detected: auction_id(%d) item_id(%I64d) keeping_id_on_item(%d) seller_id(%d) registration_tax(%I64d) bidder_list(%s) highest_bidder_id(%d) bidding_price(%I64d)",
|
|
emprs->auction_uid, emprs->item_uid, pItem->GetItemKeepingID(), emprs->seller_uid, emprs->registration_tax, emprs->bidder_list, emprs->highest_bidder_uid, emprs->highest_bidding_price );
|
|
|
|
pushLoadedItem( pItem );
|
|
AuctionManager::Instance().Push( new DB_DeleteAuctionInfo( emprs->auction_uid ) );
|
|
return false;
|
|
}
|
|
|
|
struct tm tmEndTime;
|
|
tmEndTime.tm_year = emprs->end_time.year - 1900;
|
|
tmEndTime.tm_mon = emprs->end_time.month - 1;
|
|
tmEndTime.tm_mday = emprs->end_time.day;
|
|
tmEndTime.tm_hour = emprs->end_time.hour;
|
|
tmEndTime.tm_min = emprs->end_time.minute;
|
|
tmEndTime.tm_sec = emprs->end_time.second;
|
|
tmEndTime.tm_isdst = -1;
|
|
time_t tEndTime = mktime( &tmEndTime );
|
|
|
|
int code_page = ENV().GetInt( "CodePage", CP_ACP );
|
|
char szSellerName[62];
|
|
WideCharToMultiByte( code_page, 0, emprs->seller_name, _countof( emprs->seller_name ), szSellerName, _countof( szSellerName ), NULL, NULL );
|
|
char szHighestBidderName[62];
|
|
WideCharToMultiByte( code_page, 0, emprs->highest_bidder_name, _countof( emprs->highest_bidder_name ), szHighestBidderName, _countof( szHighestBidderName ), NULL, NULL );
|
|
|
|
AuctionInfo *pAuctionInfo = new AuctionInfo( emprs->auction_uid, pItem, emprs->seller_uid, szSellerName, emprs->is_secroute_only, tEndTime, emprs->instant_purchase_price, emprs->registration_tax, emprs->bidder_list, emprs->highest_bidding_price, emprs->highest_bidder_uid, szHighestBidderName );
|
|
if( !pAuctionInfo )
|
|
{
|
|
// 여긴 데이터 자체가 잘못된 게 아니라 메모리 할당에 실패한 것이므로
|
|
// DB를 갱신하지 말고 놔둬서 다음 번 로딩 때 사용되도록 함
|
|
// 여기서 pItem을 다시 push 해두면 다른 경매에서 사용되지 않을 가능성이 높고
|
|
// (중첩 등록이 있지 않은 이상 없음) 그러면 auction_id, keeping_id 가 0으로 리셋됨
|
|
// (clearLoadedItem 함수 호출 및 역할 참조)
|
|
//pushLoadedItem( pItem );
|
|
_cprint( "Memory allocation failed for auction: auction_id(%d) item_id(%I64d)\n", emprs->auction_uid, emprs->item_uid );
|
|
FILELOG( "Memory allocation failed for auction: auction_id(%d) item_id(%I64d)", emprs->auction_uid, emprs->item_uid );
|
|
return false;
|
|
}
|
|
|
|
if( !AuctionManager::Instance().AddAuctionInfoByLoading( pAuctionInfo ) )
|
|
{
|
|
_cprint( "Duplicated auction id detected: auction_id(%d) item_id(%I64d) seller_id(%d) registration_tax(%I64d) bidder_list(%s) highest_bidder_id(%d) bidding_price(%I64d)\n",
|
|
emprs->auction_uid, emprs->item_uid, emprs->seller_uid, emprs->registration_tax, emprs->bidder_list, emprs->highest_bidder_uid, emprs->highest_bidding_price );
|
|
FILELOG( "Duplicated auction id detected: auction_id(%d) item_id(%I64d) seller_id(%d) registration_tax(%I64d) bidder_list(%s) highest_bidder_id(%d) bidding_price(%I64d)",
|
|
emprs->auction_uid, emprs->item_uid, emprs->seller_uid, emprs->registration_tax, emprs->bidder_list, emprs->highest_bidder_uid, emprs->highest_bidding_price );
|
|
|
|
pushLoadedItem( pItem );
|
|
delete pAuctionInfo;
|
|
AuctionManager::Instance().Push( new DB_DeleteAuctionInfo( emprs->auction_uid ) );
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AuctionLoader::onItemKeepingInfoData( dbItemKeeping * emprs )
|
|
{
|
|
if( !emprs->keeping_uid )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// 새로 생성될 아이템 보관 데이터 ID를 현재까지 로딩된 ID보다 커지도록 조정
|
|
UIDManager::Instance().SetMaxUsedUID( "ItemKeepingUID", emprs->keeping_uid );
|
|
|
|
StructItem *pItem = popLoadedItem( emprs->item_uid );
|
|
if( !pItem )
|
|
{
|
|
_cprint( "ItemKeepingInfo without related item detected: keeping_id(%d) item_id(%I64d) owner_id(%d)\n", emprs->keeping_uid, emprs->item_uid, emprs->owner_uid );
|
|
FILELOG( "ItemKeepingInfo without related item detected: keeping_id(%d) item_id(%I64d) owner_id(%d)", emprs->keeping_uid, emprs->item_uid, emprs->owner_uid );
|
|
|
|
AuctionManager::Instance().Push( new DB_DeleteItemKeepingInfo( emprs->keeping_uid, false, 0 ) );
|
|
return false;
|
|
}
|
|
|
|
// 아이템 데이터가 아이템 보관 데이터와 매치되지 않는 경우
|
|
if( pItem->GetItemKeepingID() != emprs->keeping_uid || pItem->GetAuctionID() > 0 )
|
|
{
|
|
_cprint( "ItemKeepingInfo with mis-related item detected: keeping_id(%d) item_id(%I64d) auction_id_on_item(%d) owner_id(%d)\n", emprs->keeping_uid, emprs->item_uid, pItem->GetAuctionID(), emprs->owner_uid );
|
|
FILELOG( "ItemKeepingInfo with mis-related item detected: keeping_id(%d) item_id(%I64d) auction_id_on_item(%d) owner_id(%d)", emprs->keeping_uid, emprs->item_uid, pItem->GetAuctionID(), emprs->owner_uid );
|
|
|
|
pushLoadedItem( pItem );
|
|
AuctionManager::Instance().Push( new DB_DeleteItemKeepingInfo( emprs->keeping_uid, false, 0 ) );
|
|
return false;
|
|
}
|
|
|
|
struct tm tmExpirationTime;
|
|
tmExpirationTime.tm_year = emprs->expiration_time.year - 1900;
|
|
tmExpirationTime.tm_mon = emprs->expiration_time.month - 1;
|
|
tmExpirationTime.tm_mday = emprs->expiration_time.day;
|
|
tmExpirationTime.tm_hour = emprs->expiration_time.hour;
|
|
tmExpirationTime.tm_min = emprs->expiration_time.minute;
|
|
tmExpirationTime.tm_sec = emprs->expiration_time.second;
|
|
tmExpirationTime.tm_isdst = -1;
|
|
time_t tExpiration = mktime( &tmExpirationTime );
|
|
|
|
ItemKeepingInfo *pItemKeeping = new ItemKeepingInfo( emprs->keeping_uid, pItem, emprs->owner_uid, tExpiration, static_cast< KEEPING_TYPE >( emprs->keeping_type ),
|
|
emprs->related_auction_id, emprs->related_item_code, emprs->related_item_enhance, emprs->related_item_level );
|
|
if( !pItemKeeping )
|
|
{
|
|
// 여긴 데이터 자체가 잘못된 게 아니라 메모리 할당에 실패한 것이므로
|
|
// DB를 갱신하지 말고 놔둬서 다음 번 로딩 때 사용되도록 함
|
|
// 여기서 pItem을 다시 push 해두면 다른 아이템 보관 데이터에서 사용되지 않을 가능성이 높고
|
|
// (중첩 등록이 있지 않은 이상 없음) 그러면 auction_id, keeping_id 가 0으로 리셋됨
|
|
// (clearLoadedItem 함수 호출 및 역할 참조)
|
|
//pushLoadedItem( pItem );
|
|
// 아이템 데이터는 더 이상 현재 서버 상태에서는 사용되지 못하므로 메모리에서 해제해 줌
|
|
StructItem::PendFreeItem( pItem );
|
|
|
|
_cprint( "Memory allocation failed for item keeping: keeping_id(%d) item_id(%I64d)\n", emprs->keeping_uid, emprs->item_uid );
|
|
FILELOG( "Memory allocation failed for item keeping: keeping_id(%d) item_id(%I64d)", emprs->keeping_uid, emprs->item_uid );
|
|
|
|
return false;
|
|
}
|
|
|
|
if( !AuctionManager::Instance().AddItemKeepingInfoByLoading( pItemKeeping ) )
|
|
{
|
|
_cprint( "Duplicated item keeping id detected: keeping_id(%d) item_id(%I64d) owner_id(%d)\n", emprs->keeping_uid, emprs->item_uid, emprs->owner_uid );
|
|
FILELOG( "Duplicated item keeping id detected: keeping_id(%d) item_id(%I64d) owner_id(%d)", emprs->keeping_uid, emprs->item_uid, emprs->owner_uid );
|
|
|
|
assert( 0 );
|
|
pushLoadedItem( pItem );
|
|
delete pItemKeeping;
|
|
AuctionManager::Instance().Push( new DB_DeleteItemKeepingInfo( emprs->keeping_uid, false, 0 ) );
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AuctionLoader::pushLoadedItem( StructItem *pItem )
|
|
{
|
|
for( std::vector< StructItem * >::iterator it = m_vLoadedItemList.begin() ; it != m_vLoadedItemList.end() ; ++it )
|
|
{
|
|
// 이미 등록된 아이템 체크
|
|
if( (*it) == pItem )
|
|
{
|
|
assert( 0 );
|
|
return false;
|
|
}
|
|
|
|
// 이미 등록되어 있는 ItemUID
|
|
if( (*it)->GetItemUID() == pItem->GetItemUID() )
|
|
{
|
|
assert( 0 );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
m_vLoadedItemList.push_back( pItem );
|
|
return true;
|
|
}
|
|
|
|
StructItem * AuctionLoader::popLoadedItem( __int64 nItemUID )
|
|
{
|
|
for( std::vector< StructItem * >::iterator it = m_vLoadedItemList.begin() ; it != m_vLoadedItemList.end() ; ++it )
|
|
{
|
|
if( (*it)->GetItemUID() == nItemUID )
|
|
{
|
|
StructItem *pItem = (*it);
|
|
m_vLoadedItemList.erase( it );
|
|
return pItem;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void AuctionLoader::clearLoadedItem()
|
|
{
|
|
for( std::vector< StructItem * >::iterator it = m_vLoadedItemList.begin() ; it != m_vLoadedItemList.end() ; ++it )
|
|
{
|
|
_cprint("Unused loaded auction item detected: sid(%I64d) auction_id(%d) keeping_id(%d)\n", (*it)->GetItemUID(), (*it)->GetAuctionID(), (*it)->GetItemKeepingID() );
|
|
FILELOG("Unused loaded auction item detected: sid(%I64d) auction_id(%d) keeping_id(%d)", (*it)->GetItemUID(), (*it)->GetAuctionID(), (*it)->GetItemKeepingID() );
|
|
AuctionManager::Instance().Push( new DB_UpdateItemAuctionKeepingID( (*it)->GetItemUID(), 0, 0 ) );
|
|
StructItem::PendFreeItem( (*it) );
|
|
}
|
|
|
|
m_vLoadedItemList.clear();
|
|
}
|
|
|
|
void AuctionLoader::clearLoadedSummonAndPet()
|
|
{
|
|
for( std::vector< StructSummon * >::iterator it = m_vLoadedSummonList.begin() ; it != m_vLoadedSummonList.end() ; ++it )
|
|
{
|
|
_cprint("Unused loaded auction/keeping summon detected: sid(%d)\n", (*it)->GetSummonSID() );
|
|
FILELOG("Unused loaded auction/keeping summon detected: sid(%d)", (*it)->GetSummonSID() );
|
|
ArcadiaServer::Instance().DeleteObject( (*it) );
|
|
}
|
|
|
|
for( std::vector< StructPet * >::iterator it = m_vLoadedPetList.begin() ; it != m_vLoadedPetList.end() ; ++it )
|
|
{
|
|
_cprint("Unused loaded auction/keeping pet detected: sid(%d)\n", (*it)->GetPetSID() );
|
|
FILELOG("Unused loaded auction/keeping pet detected: sid(%d)", (*it)->GetPetSID() );
|
|
ArcadiaServer::Instance().DeleteObject( (*it) );
|
|
}
|
|
|
|
m_vLoadedSummonList.clear();
|
|
m_vLoadedPetList.clear();
|
|
}
|
|
|
|
void AuctionLoader::clearLoadedRandomOption()
|
|
{
|
|
for( std::vector< struct ItemInstance::RANDOM_OPTION >::iterator it = m_vRandomOptionList.begin() ; it != m_vRandomOptionList.end() ; ++it )
|
|
{
|
|
_cprint("Unused loaded awaken option detected: SID(%d)\n", it->nSID );
|
|
FILELOG("Unused loaded awaken option detected: SID(%d)", it->nSID );
|
|
}
|
|
|
|
m_vRandomOptionList.clear();
|
|
}
|