//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #include "tier0/platform.h" #include "tier0/dbg.h" #include "clientframe.h" #include "framesnapshot.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" CClientFrame::CClientFrame( CFrameSnapshot *pSnapshot ) { last_entity = 0; transmit_always = NULL; // bit array used only by HLTV and replay client from_baseline = NULL; tick_count = pSnapshot->m_nTickCount; m_pSnapshot = NULL; SetSnapshot( pSnapshot ); m_pNext = NULL; } CClientFrame::CClientFrame( int tickcount ) { last_entity = 0; transmit_always = NULL; // bit array used only by HLTV and replay client from_baseline = NULL; tick_count = tickcount; m_pSnapshot = NULL; m_pNext = NULL; } CClientFrame::CClientFrame( void ) { last_entity = 0; transmit_always = NULL; // bit array used only by HLTV and replay client from_baseline = NULL; tick_count = 0; m_pSnapshot = NULL; m_pNext = NULL; } void CClientFrame::Init( int tickcount ) { tick_count = tickcount; } void CClientFrame::Init( CFrameSnapshot *pSnapshot ) { tick_count = pSnapshot->m_nTickCount; SetSnapshot( pSnapshot ); } CClientFrame::~CClientFrame() { SetSnapshot( NULL ); // Release our reference to the snapshot. if ( transmit_always != NULL ) { delete transmit_always; transmit_always = NULL; } } void CClientFrame::SetSnapshot( CFrameSnapshot *pSnapshot ) { if ( m_pSnapshot == pSnapshot ) return; if( pSnapshot ) pSnapshot->AddReference(); if ( m_pSnapshot ) m_pSnapshot->ReleaseReference(); m_pSnapshot = pSnapshot; } void CClientFrame::CopyFrame( CClientFrame &frame ) { tick_count = frame.tick_count; last_entity = frame.last_entity; SetSnapshot( frame.GetSnapshot() ); // adds reference to snapshot transmit_entity = frame.transmit_entity; if ( frame.transmit_always ) { Assert( transmit_always == NULL ); transmit_always = new CBitVec; *transmit_always = *(frame.transmit_always); } } CClientFrame *CClientFrameManager::GetClientFrame( int nTick, bool bExact ) { if ( nTick < 0 ) return NULL; CClientFrame *frame = m_Frames; CClientFrame *lastFrame = frame; while ( frame != NULL ) { if ( frame->tick_count >= nTick ) { if ( frame->tick_count == nTick ) return frame; if ( bExact ) return NULL; return lastFrame; } lastFrame = frame; frame = frame->m_pNext; } if ( bExact ) return NULL; return lastFrame; } int CClientFrameManager::CountClientFrames( void ) { #if _DEBUG int count = 0; CClientFrame *f = m_Frames; while ( f ) { count++; f = f->m_pNext; } Assert( m_nFrames == count ); #endif return m_nFrames; } //----------------------------------------------------------------------------- // Purpose: // Input : *cl - //----------------------------------------------------------------------------- int CClientFrameManager::AddClientFrame( CClientFrame *frame) { Assert( frame->tick_count > 0 ); if ( !m_Frames ) { // first client frame at all Assert( m_LastFrame == NULL && m_nFrames == 0 ); m_Frames = frame; m_LastFrame = frame; m_nFrames = 1; return 1; } Assert( m_Frames != NULL && m_nFrames > 0 ); Assert( m_LastFrame->m_pNext == NULL ); m_LastFrame->m_pNext = frame; m_LastFrame = frame; return ++m_nFrames; } void CClientFrameManager::RemoveOldestFrame( void ) { CClientFrame *frame = m_Frames; // first if ( !frame ) return; // no frames at all Assert( m_nFrames > 0 ); m_Frames = frame->m_pNext; // unlink head // deleting frame will decrease global reference counter FreeFrame( frame ); if ( --m_nFrames == 0 ) { Assert( m_LastFrame == frame && m_Frames == NULL ); m_LastFrame = NULL; } } void CClientFrameManager::DeleteClientFrames(int nTick) { if ( nTick < 0 ) { while ( m_nFrames > 0 ) { RemoveOldestFrame(); } } else { CClientFrame *frame = m_Frames; // rebuild m_LastFrame while iterating forward through the list m_LastFrame = NULL; while ( frame ) { if ( frame->tick_count < nTick ) { // Delete this frame CClientFrame* next = frame->m_pNext; if ( m_Frames == frame ) m_Frames = next; FreeFrame( frame ); if ( --m_nFrames == 0 ) { Assert( next == NULL ); m_LastFrame = m_Frames = NULL; break; } Assert( m_LastFrame != frame && m_nFrames > 0 ); frame = next; if ( m_LastFrame ) m_LastFrame->m_pNext = next; } else { Assert( m_LastFrame == NULL || m_LastFrame->m_pNext == frame ); m_LastFrame = frame; frame = frame->m_pNext; } } } } //----------------------------------------------------------------------------- // Class factory for frames //----------------------------------------------------------------------------- CClientFrame* CClientFrameManager::AllocateFrame() { return m_ClientFramePool.Alloc(); } void CClientFrameManager::FreeFrame( CClientFrame* pFrame ) { if ( pFrame->IsMemPoolAllocated() ) { m_ClientFramePool.Free( pFrame ); } else { delete pFrame; } } CClientFrameManager::CClientFrameManager( void ) : m_ClientFramePool( MAX_CLIENT_FRAMES, CUtlMemoryPool::GROW_SLOW ), m_Frames(NULL), m_LastFrame(NULL), m_nFrames(0) { } CClientFrameManager::~CClientFrameManager( void ) { DeleteClientFrames( -1 ); Assert( m_nFrames == 0 ); }