Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
5.2 KiB

5 years ago
//========= Copyright Valve Corporation, All rights reserved. ============//
//
//=======================================================================================//
#include "baserecordingsession.h"
#include "baserecordingsessionblock.h"
#include "replay/irecordingsessionblockmanager.h"
#include "replay/replayutils.h"
#include "replay/iclientreplaycontext.h"
#include "replay/shared_defs.h"
#include "KeyValues.h"
#include "replay/replayutils.h"
#include "replay/ireplaycontext.h"
#include "filesystem.h"
#include "iserver.h"
#include "replaysystem.h"
#include "utlbuffer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//----------------------------------------------------------------------------------------
CBaseRecordingSession::CBaseRecordingSession( IReplayContext *pContext )
: m_pContext( pContext ),
m_bRecording( false ),
m_bAutoDelete( false ),
m_bBlocksLoaded( false ),
m_flStartTime( 0.0f )
{
}
CBaseRecordingSession::~CBaseRecordingSession()
{
}
void CBaseRecordingSession::AddBlock( CBaseRecordingSessionBlock *pBlock )
{
AddBlock( pBlock, false );
}
bool CBaseRecordingSession::Read( KeyValues *pIn )
{
if ( !BaseClass::Read( pIn ) )
return false;
m_strName = pIn->GetString( "name" );
if ( m_strName.IsEmpty() )
{
CUtlBuffer buf;
pIn->RecursiveSaveToFile( buf, 0 );
IF_REPLAY_DBG( Warning( "Session with no session name found - aborting load for this session. Data:\n---\n%s\n---\n", (const char *)buf.Base() ) );
return false;
}
m_bRecording = pIn->GetBool( "recording" );
m_strBaseDownloadURL = pIn->GetString( "base_download_url" );
m_nServerStartRecordTick = pIn->GetInt( "server_start_record_tick", -1 );
return true;
}
void CBaseRecordingSession::Write( KeyValues *pOut )
{
BaseClass::Write( pOut );
pOut->SetString( "name", m_strName.Get() );
pOut->SetInt( "recording", m_bRecording ? 1 : 0 );
pOut->SetString( "base_download_url", m_strBaseDownloadURL.Get() );
pOut->SetInt( "server_start_record_tick", m_nServerStartRecordTick );
}
const char *CBaseRecordingSession::GetSubKeyTitle() const
{
return m_strName.Get();
}
const char *CBaseRecordingSession::GetPath() const
{
return Replay_va( "%s%s%c", m_pContext->GetBaseDir(), SUBDIR_SESSIONS, CORRECT_PATH_SEPARATOR );
}
const char *CBaseRecordingSession::GetSessionInfoURL() const
{
return Replay_va( "%s%s.%s", m_strBaseDownloadURL.Get(), m_strName.Get(), GENERIC_FILE_EXTENSION );
}
void CBaseRecordingSession::LoadBlocksForSession()
{
if ( m_bBlocksLoaded )
return;
IRecordingSessionBlockManager *pBlockManager = m_pContext->GetRecordingSessionBlockManager();
// Peek in directory and load files based on what's there
FileFindHandle_t hFind;
CFmtStr fmtPath( "%s%s*.%s", pBlockManager->GetBlockPath(), m_strName.Get(), GENERIC_FILE_EXTENSION );
const char *pFilename = g_pFullFileSystem->FindFirst( fmtPath.Access(), &hFind );
while ( pFilename )
{
// Load the block - this will add the block to this session
pBlockManager->LoadBlockFromFileName( pFilename, this );
// Get next file
pFilename = g_pFullFileSystem->FindNext( hFind );
}
// Blocks loaded
m_bBlocksLoaded = true;
}
void CBaseRecordingSession::OnDelete()
{
BaseClass::OnDelete();
// Dynamically load blocks if necessary, then delete from the block manager and from disk
DeleteBlocks();
}
void CBaseRecordingSession::DeleteBlocks()
{
if ( !m_bBlocksLoaded )
{
// Load blocks now based on the session name
LoadBlocksForSession();
}
// Delete all blocks associated w/ the session
FOR_EACH_VEC( m_vecBlocks, i )
{
CBaseRecordingSessionBlock *pCurBlock = m_vecBlocks[ i ];
m_pContext->GetRecordingSessionBlockManager()->DeleteBlock( pCurBlock );
}
}
void CBaseRecordingSession::OnUnload()
{
BaseClass::OnUnload();
FOR_EACH_VEC( m_vecBlocks, i )
{
CBaseRecordingSessionBlock *pCurBlock = m_vecBlocks[ i ];
m_pContext->GetRecordingSessionBlockManager()->UnloadBlock( pCurBlock );
}
}
void CBaseRecordingSession::PopulateWithRecordingData( int nCurrentRecordingStartTick )
{
Assert( nCurrentRecordingStartTick >= 0 );
m_strBaseDownloadURL = Replay_GetDownloadURL();
m_bRecording = true;
m_nServerStartRecordTick = nCurrentRecordingStartTick;
}
void CBaseRecordingSession::AddBlock( CBaseRecordingSessionBlock *pBlock, bool bFlagForFlush )
{
Assert( pBlock->m_hSession == GetHandle() );
Assert( m_vecBlocks.Find( pBlock ) == m_vecBlocks.InvalidIndex() );
m_vecBlocks.Insert( pBlock );
if ( bFlagForFlush )
{
// Mark as dirty
m_pContext->GetRecordingSessionManager()->FlagSessionForFlush( this, false );
}
m_bBlocksLoaded = true;
}
int CBaseRecordingSession::FindBlock( CBaseRecordingSessionBlock *pBlock ) const
{
int itResult = m_vecBlocks.Find( pBlock );
if ( itResult == m_vecBlocks.InvalidIndex() )
return -1;
return itResult;
}
bool CBaseRecordingSession::ShouldDitchSession() const
{
return m_bAutoDelete;
}
//----------------------------------------------------------------------------------------
bool CBaseRecordingSession::CLessFunctor::Less( const CBaseRecordingSessionBlock *pSrc1, const CBaseRecordingSessionBlock *pSrc2, void *pContext )
{
return pSrc1->m_iReconstruction < pSrc2->m_iReconstruction;
}
//----------------------------------------------------------------------------------------