csgo-2018-source/engine/clientframe.cpp

282 lines
5.4 KiB
C++
Raw Normal View History

2021-07-25 12:11:47 +08:00
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "tier0/platform.h"
#include "tier0/dbg.h"
#include "clientframe.h"
#include "packed_entity.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<MAX_EDICTS>;
*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 )
{
int count = 0;
CClientFrame *f = m_Frames;
while ( f )
{
count++;
f = f->m_pNext;
}
return count;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *cl -
//-----------------------------------------------------------------------------
int CClientFrameManager::AddClientFrame( CClientFrame *frame)
{
Assert( frame->tick_count > 0 );
if ( !m_Frames )
{
// first client frame at all
m_Frames = frame;
return 1;
}
CClientFrame *f = m_Frames;
int count = 1;
while ( f->m_pNext )
{
f = f->m_pNext;
++count;
}
++count;
f->m_pNext = frame;
return count;
}
void CClientFrameManager::RemoveOldestFrame( void )
{
CClientFrame *frame = m_Frames; // first
if ( !frame )
return; // no frames at all
m_Frames = frame->m_pNext; // unlink head
// deleting frame will decrease global reference counter
FreeFrame( frame );
}
void CClientFrameManager::DeleteClientFrames(int nTick)
{
CClientFrame *frame = m_Frames; // first
CClientFrame *prev = NULL; // last
while ( frame )
{
// remove frame if tick small nTick
// remove all frames if nTick == -1
if ( (nTick < 0) || (frame->tick_count < nTick) )
{
// removed frame
if ( prev )
{
prev->m_pNext = frame->m_pNext;
// deleting frame will decrease global reference counter
FreeFrame( frame );
frame = prev->m_pNext;
}
else
{
m_Frames = frame->m_pNext;
FreeFrame( frame );
frame = m_Frames;
}
}
else
{
// go to next frame
prev = frame;
frame = frame->m_pNext;
}
}
}
bool CClientFrameManager::DeleteUnusedClientFrame( CClientFrame* pFrameToDelete )
{
// Call this to deallocate an unused frame (this should NOT have been added to m_Frames)
CClientFrame **ppFrame = &m_Frames; // address of pointer to first frame
while ( *ppFrame )
{
if ( *ppFrame == pFrameToDelete )
{
Assert( !"ERROR: DeleteUnusedClientFrame called incorrectly...\n" );
return false;
}
ppFrame = &( (*ppFrame)->m_pNext );
}
FreeFrame( pFrameToDelete );
return true;
}
//-----------------------------------------------------------------------------
// Class factory for frames
//-----------------------------------------------------------------------------
CClientFrame* CClientFrameManager::AllocateFrame()
{
return m_ClientFramePool.Alloc();
}
CClientFrame* CClientFrameManager::AllocateAndInitFrame( int nTick )
{
CClientFrame* pFrame = m_ClientFramePool.Alloc();
pFrame->Init( nTick );
if ( m_Frames && m_Frames->tick_count > nTick )
{
while ( m_Frames )
{
CClientFrame* pNext = m_Frames->m_pNext;
FreeFrame( m_Frames );
m_Frames = pNext;
}
}
return pFrame;
}
void CClientFrameManager::FreeFrame( CClientFrame* pFrame )
{
if ( pFrame->IsMemPoolAllocated() )
{
m_ClientFramePool.Free( pFrame );
}
else
{
delete pFrame;
}
}