diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /replay/common/replay.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'replay/common/replay.cpp')
| -rw-r--r-- | replay/common/replay.cpp | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/replay/common/replay.cpp b/replay/common/replay.cpp new file mode 100644 index 0000000..1d56def --- /dev/null +++ b/replay/common/replay.cpp @@ -0,0 +1,374 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +//=======================================================================================// + +#include "replay/replay.h" +#include "replay/iclientreplaycontext.h" +#include "replay/ireplaymanager.h" +#include "replay/replayutils.h" +#include "replay/screenshot.h" +#include "replay/shared_defs.h" +#include "replay/ireplayscreenshotmanager.h" +#include "replay/ireplayperformancemanager.h" +#include "replay/performance.h" +#include "KeyValues.h" +#include "filesystem.h" +#include "vgui/ILocalize.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//---------------------------------------------------------------------------------------- + +extern IClientReplayContext *g_pClientReplayContext; +extern vgui::ILocalize *g_pVGuiLocalize; + +//---------------------------------------------------------------------------------------- + +CReplay::CReplay() +: m_pDownloadEventHandler( NULL ), + m_pUserData( NULL ), + m_bComplete( false ), + m_bRequestedByUser( false ), + m_bSaved( false ), + m_bRendered( false ), + m_bDirty( false ), + m_bSavedDuringThisSession( true ), + m_flLength( 0 ), + m_nPlayerSlot( -1 ), + m_nSpawnTick( -1 ), + m_nDeathTick( -1 ), + m_iMaxSessionBlockRequired( 0 ), + m_nStatus( REPLAYSTATUS_INVALID ), + m_hSession( REPLAY_HANDLE_INVALID ), + m_pFileURL( NULL ), + m_nPostDeathRecordTime( 0 ), + m_flStartTime( 0.0f ), + m_flNextUpdateTime( 0.0f ) +{ + m_wszTitle[0] = L'\0'; + m_szMapName[0] = 0; +} + +bool CReplay::IsDownloaded() const +{ + return m_nStatus == REPLAYSTATUS_READYTOCONVERT; +} + +const CReplayPerformance *CReplay::GetPerformance( int i ) const +{ + return const_cast< CReplay * >( this )->GetPerformance( i ); +} + +CReplayPerformance *CReplay::GetPerformance( int i ) +{ + if ( i < 0 || i >= m_vecPerformances.Count() ) + return NULL; + + return m_vecPerformances[ i ]; +} + +bool CReplay::FindPerformance( CReplayPerformance *pPerformance, int &iResult ) +{ + const int it = m_vecPerformances.Find( pPerformance ); + if ( it == m_vecPerformances.InvalidIndex() ) + { + iResult = -1; + return false; + } + + iResult = it; + return true; +} + +CReplayPerformance *CReplay::GetPerformanceWithTitle( const wchar_t *pTitle ) +{ + FOR_EACH_VEC( m_vecPerformances, i ) + { + CReplayPerformance *pCurPerformance = m_vecPerformances[ i ]; + if ( !V_wcscmp( pTitle, pCurPerformance->m_wszTitle ) ) + { + return pCurPerformance; + } + } + return NULL; +} + +CReplayPerformance *CReplay::AddNewPerformance( bool bGenTitle/*=true*/, bool bGenFilename/*=true*/ ) +{ + // Create a performance + IReplayPerformanceManager *pPerformanceManager = g_pClientReplayContext->GetPerformanceManager(); + CReplayPerformance *pPerformance = pPerformanceManager->CreatePerformance( this ); + + if ( bGenTitle ) + { + // Give the performance a name + pPerformance->AutoNameIfHasNoTitle( m_szMapName ); + } + + if ( bGenFilename ) + { + // Generate a filename for the new performance + pPerformance->SetFilename( pPerformanceManager->GeneratePerformanceFilename( this ) ); + } + + // Cache + m_vecPerformances.AddToTail( pPerformance ); + + return pPerformance; +} + +void CReplay::AddPerformance( KeyValues *pIn ) +{ + // Create a performance + IReplayPerformanceManager *pPerformanceManager = g_pClientReplayContext->GetPerformanceManager(); + CReplayPerformance *pPerformance = pPerformanceManager->CreatePerformance( this ); + + // Read + pPerformance->Read( pIn ); + + // Cache + m_vecPerformances.AddToTail( pPerformance ); +} + +void CReplay::AddPerformance( CReplayPerformance *pPerformance ) +{ + Assert( pPerformance ); + m_vecPerformances.AddToTail( pPerformance ); +} + +const CReplayTime &CReplay::GetItemDate() const +{ + return m_RecordTime; +} + +bool CReplay::IsItemRendered() const +{ + return m_bRendered; +} + +CReplay *CReplay::GetItemReplay() +{ + return this; +} + +ReplayHandle_t CReplay::GetItemReplayHandle() const +{ + return GetHandle(); +} + +QueryableReplayItemHandle_t CReplay::GetItemHandle() const +{ + return GetHandle(); +} + +const wchar_t *CReplay::GetItemTitle() const +{ + return m_wszTitle; +} + +void CReplay::SetItemTitle( const wchar_t *pTitle ) +{ + V_wcsncpy( m_wszTitle, pTitle, sizeof( m_wszTitle ) ); +} + +float CReplay::GetItemLength() const +{ + return m_flLength; +} + +void *CReplay::GetUserData() +{ + return m_pUserData; +} + +void CReplay::SetUserData( void* pUserData ) +{ + m_pUserData = pUserData; +} + +bool CReplay::IsItemAMovie() const +{ + return false; +} + +void CReplay::AddScreenshot( int nWidth, int nHeight, const char *pBaseFilename ) +{ + m_vecScreenshots.AddToTail( new CReplayScreenshot( nWidth, nHeight, pBaseFilename ) ); +} + +void CReplay::AutoNameTitleIfEmpty() +{ + // Autoname it + if ( !m_wszTitle[0] ) + { + Replay_GetAutoName( m_wszTitle, sizeof( m_wszTitle ), m_szMapName ); + } +} + +const char *CReplay::GetSubKeyTitle() const +{ + return Replay_va( "replay_%i", GetHandle() ); +} + +const char *CReplay::GetPath() const +{ + return Replay_va( "%s%s%c", g_pClientReplayContext->GetBaseDir(), SUBDIR_REPLAYS, CORRECT_PATH_SEPARATOR ); +} + +void CReplay::OnDelete() +{ + BaseClass::OnDelete(); + + // Delete reconstructed replay if one exists + if ( HasReconstructedReplay() ) + { + g_pFullFileSystem->RemoveFile( m_strReconstructedFilename.Get() ); + } + + // Delete screenshots + g_pClientReplayContext->GetScreenshotManager()->DeleteScreenshotsForReplay( this ); + + // TODO: Delete performance(s) +} + +bool CReplay::Read( KeyValues *pIn ) +{ + if ( !BaseClass::Read( pIn ) ) + return false; + + m_hSession = (ReplayHandle_t)pIn->GetInt( "session", REPLAY_HANDLE_INVALID ); + V_strcpy_safe( m_szMapName, pIn->GetString( "map", "" ) ); + m_nSpawnTick = pIn->GetInt( "spawn_tick", -1 ); + m_nDeathTick = pIn->GetInt( "death_tick", -1 ); + m_nStatus = static_cast< CReplay::ReplayStatus_t >( pIn->GetInt( "status", (int)CReplay::REPLAYSTATUS_INVALID ) ); + m_bComplete = pIn->GetInt( "complete" ) != 0; + m_flLength = pIn->GetFloat( "length" ); + m_nPostDeathRecordTime = pIn->GetInt( "postdeathrecordtime" ); + m_bRendered = pIn->GetInt( "rendered" ) != 0; + m_nPlayerSlot = pIn->GetInt( "player_slot", -1 ); + m_iMaxSessionBlockRequired = pIn->GetInt( "max_block", 0 ); Assert( m_iMaxSessionBlockRequired >= 0 ); + m_flStartTime = pIn->GetFloat( "start_time", -1.0f ); Assert( m_flStartTime >= 0.0f ); + V_wcsncpy( m_wszTitle, pIn->GetWString( "title" ), sizeof( m_wszTitle ) ); + + // Read reconstructed filename and infer path + const char *pReplaysDir = g_pClientReplayContext->GetReplayManager()->GetReplaysDir(); + const char *pReconFilename = pIn->GetString( "recon_filename" ); + if ( pReconFilename[0] != 0 ) + { + m_strReconstructedFilename = Replay_va( "%s%s", pReplaysDir, pReconFilename ); + } + + // Read screenshots + KeyValues *pScreenshots = pIn->FindKey( "screenshots" ); + if ( pScreenshots ) + { + FOR_EACH_TRUE_SUBKEY( pScreenshots, pScreenshot ) + { + int nWidth = pScreenshot->GetInt( "width" ); + int nHeight = pScreenshot->GetInt( "height" ); + const char *pBaseFilename = pScreenshot->GetString( "base_filename" ); + AddScreenshot( nWidth, nHeight, pBaseFilename ); + } + } + + // Read performances + KeyValues *pPerformances = pIn->FindKey( "edits" ); + if ( pPerformances ) + { + FOR_EACH_TRUE_SUBKEY( pPerformances, pPerformance ) + { + AddPerformance( pPerformance ); + } + } + + // Record time + KeyValues *pRecordTimeSubKey = pIn->FindKey( "record_time" ); + if ( pRecordTimeSubKey ) + { + m_RecordTime.Read( pRecordTimeSubKey ); + } + + // Mark replay as saved, since it was just loaded from disk + m_bSaved = true; + + return true; +} + +void CReplay::Write( KeyValues *pOut ) +{ + BaseClass::Write( pOut ); + + pOut->SetString( "map", m_szMapName ); + pOut->SetInt( "session", m_hSession ); + pOut->SetInt( "spawn_tick", m_nSpawnTick ); + pOut->SetInt( "death_tick", m_nDeathTick ); + pOut->SetInt( "status", static_cast< int >( m_nStatus ) ); + pOut->SetInt( "complete", static_cast< int >( m_bComplete ) ); + pOut->SetFloat( "length", m_flLength ); + pOut->SetInt( "postdeathrecordtime", m_nPostDeathRecordTime ); + pOut->SetInt( "rendered", m_bRendered ); + pOut->SetInt( "player_slot", m_nPlayerSlot ); + pOut->SetInt( "max_block", m_iMaxSessionBlockRequired ); + pOut->SetFloat( "start_time", m_flStartTime ); + pOut->SetWString( "title", m_wszTitle ); + + // Store only filename for reconstructed .dem + if ( !m_strReconstructedFilename.IsEmpty() ) + { + const char *pReconFilename = V_UnqualifiedFileName( m_strReconstructedFilename.Get() ); + if ( pReconFilename[0] ) + { + pOut->SetString( "recon_filename", pReconFilename ); + } + } + + // Write screenshots + KeyValues *pScreenshots = new KeyValues( "screenshots" ); + pOut->AddSubKey( pScreenshots ); + for ( int i = 0; i < m_vecScreenshots.Count(); ++i ) + { + KeyValues *pScreenshotOut = new KeyValues( "screenshot" ); + CReplayScreenshot *pScreenshot = m_vecScreenshots[ i ]; + pScreenshotOut->SetInt( "width", pScreenshot->m_nWidth ); + pScreenshotOut->SetInt( "height", pScreenshot->m_nHeight ); + pScreenshotOut->SetString( "base_filename", pScreenshot->m_szBaseFilename ); + pScreenshots->AddSubKey( pScreenshotOut ); + } + + // Write performances + KeyValues *pPerformances = new KeyValues( "edits" ); + pOut->AddSubKey( pPerformances ); + for ( int i = 0; i < m_vecPerformances.Count(); ++i ) + { + KeyValues *pPerfOut = new KeyValues( "edit" ); + CReplayPerformance *pPerformance = m_vecPerformances[ i ]; + pPerformance->Write( pPerfOut ); + pPerformances->AddSubKey( pPerfOut ); + } + + KeyValues *pRecordTime = new KeyValues( "record_time" ); + pOut->AddSubKey( pRecordTime ); + m_RecordTime.Write( pRecordTime ); + + // Mark as saved + m_bSaved = true; +} + +bool CReplay::HasReconstructedReplay() const +{ + return !m_strReconstructedFilename.IsEmpty() && + g_pFullFileSystem->FileExists( m_strReconstructedFilename.Get() ); +} + +bool CReplay::IsSignificantBlock( int iBlockReconstruction ) const +{ + return iBlockReconstruction <= m_iMaxSessionBlockRequired; +} + +void CReplay::OnComplete() +{ + AutoNameTitleIfEmpty(); +} + +//---------------------------------------------------------------------------------------- |