// IdentifyQueue.cpp : Implementation of CIdentifyQueue #include "stdafx.h" #include "IdentifyQueue.h" // Timeout in millisec to re-request ID #define TIMEOUT 700 enum AcMessages { msgGameEvent = 0xF7B0, msgUnknown = 0 }; enum AcGameEvents { gevIDItem = 0x00C9, gevUnknown = 0 }; // CIdentifyQueue HRESULT CIdentifyQueue::onInitialize() { if( m_pService->get_Decal( &m_pDecal ) == S_OK ) { if( m_pDecal->get_Hooks( &m_pHooks ) == S_OK ) { m_pHooks->SetIDFilter( this ); long lRequestIDMemloc; if( m_pHooks->QueryMemLoc( _bstr_t( "ItemEventAppraise" ), &lRequestIDMemloc ) == S_OK ) { if( lRequestIDMemloc != 0 ) { m_pfRequestFunc = reinterpret_cast< RequestPtr >( lRequestIDMemloc ); return S_OK; } } } } m_pfRequestFunc = NULL; m_pService.Release(); return E_FAIL; } HRESULT CIdentifyQueue::onTerminate() { m_pDecal.Release(); m_pHooks.Release(); m_pfRequestFunc = NULL; return S_OK; } STDMETHODIMP CIdentifyQueue::DispatchServer( IMessage2 *pMsg ) { long lType; pMsg->get_Type( &lType ); CComPtr< IMessageIterator > pMembers; pMsg->get_Begin( &pMembers ); switch( lType ) { case msgGameEvent: MsgGameEvent( pMembers ); break; } if( m_Queue.empty() ) return S_OK; // Check for timeout... if( m_bWaiting ) { if( abs( m_Queue[0]->lTime - timeGetTime() ) > TIMEOUT ) { if( ++m_lAttempts >= 3 ) { m_lAttempts = 0; m_Queue.erase( m_Queue.begin() ); m_bWaiting = false; Request(); } else { m_Queue[0]->lTime = timeGetTime(); m_bWaiting = false; Request(); } } } return S_OK; } STDMETHODIMP CIdentifyQueue::AddToQueue( long lObjectID ) { if( lObjectID == 0 ) return S_OK; if( !m_Queue.empty() ) { for( IDContainer::iterator pDeque = m_Queue.begin(); pDeque != m_Queue.end(); ++pDeque ) { if( (*pDeque)->lObjectID == lObjectID ) return S_OK; } } IDStruct *QueueObj = new IDStruct(); QueueObj->lObjectID = lObjectID; QueueObj->lTime = timeGetTime(); m_Queue.push_back( QueueObj ); if( !m_bWaiting ) Request(); return S_OK; } STDMETHODIMP CIdentifyQueue::ShortcircuitID( long lObjectID ) { m_lLastManualAttempt = lObjectID; if( !m_Queue.empty() ) { for( IDContainer::iterator pDeque = m_Queue.begin(); pDeque != m_Queue.end(); ++pDeque ) { if ( (*pDeque)->lObjectID == lObjectID ) { m_Queue.erase( pDeque ); break; } } } IDStruct *QueueObj = new IDStruct(); QueueObj->lObjectID = lObjectID; QueueObj->lTime = timeGetTime(); m_Queue.push_front( QueueObj ); if( !m_bWaiting ) Request(); return S_OK; } void CIdentifyQueue::MsgGameEvent( IMessageIterator *pMembers ) { long lEvent; pMembers->get_NextInt( _bstr_t( "event" ), &lEvent ); switch( lEvent ) { case gevIDItem: MsgIDItem( pMembers ); break; } } void CIdentifyQueue::MsgIDItem( IMessageIterator *pMembers ) { if( m_Queue.empty() ) return; long lObjectID; pMembers->get_NextInt( _bstr_t( "object" ), &lObjectID ); for( IDContainer::iterator pDeque = m_Queue.begin(); pDeque != m_Queue.end(); pDeque++ ) { if ( (*pDeque)->lObjectID == lObjectID ) { m_lAttempts = 0; pDeque = m_Queue.erase( pDeque ); break; } } if( m_bWaiting ) { m_bWaiting = false; Request(); } } void CIdentifyQueue::Request() { if( !m_bWaiting ) { if( m_Queue.empty() ) { m_pfRequestFunc( 0 ); return; } IDStruct *pQueueBegin = *m_Queue.begin(); m_pfRequestFunc( pQueueBegin->lObjectID ); m_bWaiting = true; if( pQueueBegin->lObjectID == 0 ) { m_bWaiting = false; m_Queue.erase( m_Queue.begin() ); Request(); } } }