mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-07 17:29:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
//=======================================================================================//
|
||||
|
||||
#include "replay/basereplayserializeable.h"
|
||||
#include "replay/replayutils.h"
|
||||
#include "KeyValues.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "replay/shared_defs.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
CBaseReplaySerializeable::CBaseReplaySerializeable()
|
||||
: m_hThis( REPLAY_HANDLE_INVALID ),
|
||||
m_bLocked( false )
|
||||
{
|
||||
}
|
||||
|
||||
void CBaseReplaySerializeable::SetHandle( ReplayHandle_t h )
|
||||
{
|
||||
m_hThis = h;
|
||||
}
|
||||
|
||||
ReplayHandle_t CBaseReplaySerializeable::GetHandle() const
|
||||
{
|
||||
return m_hThis;
|
||||
}
|
||||
|
||||
bool CBaseReplaySerializeable::Read( KeyValues *pIn )
|
||||
{
|
||||
m_hThis = (ReplayHandle_t)pIn->GetInt( "handle" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBaseReplaySerializeable::Write( KeyValues *pOut )
|
||||
{
|
||||
pOut->SetInt( "handle", (int)m_hThis );
|
||||
}
|
||||
|
||||
const char *CBaseReplaySerializeable::GetFullFilename() const
|
||||
{
|
||||
const char *pPath = GetPath();
|
||||
const char *pFilename = GetFilename();
|
||||
|
||||
if ( !pPath || !pPath[0] || !pFilename || !pFilename[0] )
|
||||
return NULL;
|
||||
|
||||
return Replay_va( "%s%s", pPath, pFilename );
|
||||
}
|
||||
|
||||
const char *CBaseReplaySerializeable::GetFilename() const
|
||||
{
|
||||
return Replay_va( "%s.%s", GetSubKeyTitle(), GENERIC_FILE_EXTENSION );
|
||||
}
|
||||
|
||||
const char *CBaseReplaySerializeable::GetDebugName() const
|
||||
{
|
||||
return GetSubKeyTitle();
|
||||
}
|
||||
|
||||
void CBaseReplaySerializeable::SetLocked( bool bLocked )
|
||||
{
|
||||
m_bLocked = bLocked;
|
||||
}
|
||||
|
||||
bool CBaseReplaySerializeable::IsLocked() const
|
||||
{
|
||||
return m_bLocked;
|
||||
}
|
||||
|
||||
void CBaseReplaySerializeable::OnDelete()
|
||||
{
|
||||
}
|
||||
|
||||
void CBaseReplaySerializeable::OnUnload()
|
||||
{
|
||||
}
|
||||
|
||||
void CBaseReplaySerializeable::OnAddedToDirtyList()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,15 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// HEADERS.VPC - Allows for sync'd inclusion of headers for replay_common.lib
|
||||
// other vpc's.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Folder $REPLAY_COMMON_HEADERS_TITLE
|
||||
{
|
||||
$File "$SRCDIR\common\replay\replay.h"
|
||||
$File "$SRCDIR\common\replay\replaylib.h"
|
||||
$File "$SRCDIR\common\replay\performance.h"
|
||||
$File "$SRCDIR\common\replay\replaytime.h"
|
||||
$File "$SRCDIR\common\replay\replayutils.h"
|
||||
$File "$SRCDIR\common\replay\screenshot.h"
|
||||
$File "$SRCDIR\common\replay\shared_defs.h"
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
//=======================================================================================//
|
||||
|
||||
#include "replay/performance.h"
|
||||
#include "replay/iclientreplaycontext.h"
|
||||
#include "replay/ireplayperformancemanager.h"
|
||||
#include "replay/replayutils.h"
|
||||
#include "KeyValues.h"
|
||||
#include "fmtstr.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
extern IClientReplayContext *g_pClientReplayContext;
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
CReplayPerformance::CReplayPerformance( CReplay *pReplay )
|
||||
: m_pReplay( pReplay ),
|
||||
m_nTickIn( -1 ),
|
||||
m_nTickOut( -1 )
|
||||
{
|
||||
Assert( pReplay );
|
||||
m_szBaseFilename[ 0 ] = '\0';
|
||||
m_wszTitle[0] = L'\0';
|
||||
}
|
||||
|
||||
CReplayPerformance::CReplayPerformance( const CReplayPerformance *pPerformance )
|
||||
{
|
||||
Copy( pPerformance );
|
||||
}
|
||||
|
||||
void CReplayPerformance::Read( KeyValues *pIn )
|
||||
{
|
||||
SetFilename( pIn->GetString( "filename" ) );
|
||||
m_nTickIn = pIn->GetInt( "tick_in", -1 );
|
||||
m_nTickOut = pIn->GetInt( "tick_out", -1 );
|
||||
V_wcsncpy( m_wszTitle, pIn->GetWString( "title" ), sizeof( m_wszTitle ) );
|
||||
}
|
||||
|
||||
void CReplayPerformance::Write( KeyValues *pOut )
|
||||
{
|
||||
pOut->SetString( "filename", m_szBaseFilename );
|
||||
pOut->SetInt( "tick_in", m_nTickIn );
|
||||
pOut->SetInt( "tick_out", m_nTickOut );
|
||||
pOut->SetWString( "title", m_wszTitle );
|
||||
}
|
||||
|
||||
void CReplayPerformance::Copy( const CReplayPerformance *pSrc )
|
||||
{
|
||||
V_wcsncpy( m_wszTitle, pSrc->m_wszTitle, sizeof( m_wszTitle ) );
|
||||
V_strcpy( m_szBaseFilename, pSrc->m_szBaseFilename );
|
||||
|
||||
m_pReplay = pSrc->m_pReplay;
|
||||
|
||||
CopyTicks( pSrc );
|
||||
}
|
||||
|
||||
void CReplayPerformance::CopyTicks( const CReplayPerformance *pSrc )
|
||||
{
|
||||
m_nTickIn = pSrc->m_nTickIn;
|
||||
m_nTickOut = pSrc->m_nTickOut;
|
||||
}
|
||||
|
||||
void CReplayPerformance::SetFilename( const char *pFilename )
|
||||
{
|
||||
V_strcpy( m_szBaseFilename, pFilename );
|
||||
}
|
||||
|
||||
const char *CReplayPerformance::GetFullPerformanceFilename()
|
||||
{
|
||||
return Replay_va( "%s%s", g_pClientReplayContext->GetPerformanceManager()->GetFullPath(), m_szBaseFilename );
|
||||
}
|
||||
|
||||
void CReplayPerformance::AutoNameIfHasNoTitle( const char *pMapName )
|
||||
{
|
||||
if ( !m_wszTitle[ 0 ] )
|
||||
{
|
||||
Replay_GetAutoName( m_wszTitle, sizeof( m_wszTitle ), pMapName );
|
||||
}
|
||||
}
|
||||
|
||||
void CReplayPerformance::SetTitle( const wchar_t *pTitle )
|
||||
{
|
||||
V_wcsncpy( m_wszTitle, pTitle, sizeof( m_wszTitle ) );
|
||||
}
|
||||
|
||||
CReplayPerformance *CReplayPerformance::MakeCopy() const
|
||||
{
|
||||
return new CReplayPerformance( this );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,36 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// REPLAY_COMMON.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$Macro REPLAY_COMMON_HEADERS_TITLE "Headers"
|
||||
$Macro OUTLIBDIR "$LIBCOMMON"
|
||||
|
||||
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE;$SRCDIR\dx9sdk\include" [$WINDOWS]
|
||||
$AdditionalIncludeDirectories "$BASE;$SRCDIR\x360xdk\include\win32\vs2005" [$WINDOWS]
|
||||
}
|
||||
}
|
||||
|
||||
$Project "replay_common"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "replay.cpp"
|
||||
$File "replaylib.cpp"
|
||||
$File "basereplayserializeable.cpp"
|
||||
$File "performance.cpp"
|
||||
$File "replaytime.cpp"
|
||||
$File "replayutils.cpp"
|
||||
$File "screenshot.cpp"
|
||||
}
|
||||
|
||||
$Include "$SRCDIR\replay\common\headers.vpc"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
//=======================================================================================//
|
||||
|
||||
#include "replay/replaylib.h"
|
||||
#include "replay/replayutils.h"
|
||||
#include "replay/iclientreplaycontext.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
IClientReplayContext *g_pClientReplayContext = NULL;
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
bool ReplayLib_Init( const char *pGameDir, IClientReplayContext *pClientReplayContext )
|
||||
{
|
||||
Replay_SetGameDir( pGameDir );
|
||||
|
||||
g_pClientReplayContext = pClientReplayContext;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,274 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
//=======================================================================================//
|
||||
|
||||
#include "replay/replaytime.h"
|
||||
#include "KeyValues.h"
|
||||
#include <time.h>
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
CReplayTime::CReplayTime()
|
||||
: m_fDate( 0 ),
|
||||
m_fTime( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
void CReplayTime::InitDateAndTimeToNow()
|
||||
{
|
||||
tm now;
|
||||
VCRHook_LocalTime( &now );
|
||||
SetDate( now.tm_mday, now.tm_mon + 1, now.tm_year + 1900 );
|
||||
SetTime( now.tm_hour, now.tm_min, now.tm_sec );
|
||||
}
|
||||
|
||||
void CReplayTime::SetDate( int nDay, int nMonth, int nYear )
|
||||
{
|
||||
Assert( nDay >= 1 && nDay <= 31 );
|
||||
Assert( nMonth >= 1 && nMonth <= 12 );
|
||||
Assert( nYear >= 2009 && nYear <= 2136 );
|
||||
|
||||
m_fDate = nDay - 1;
|
||||
m_fDate |= ( ( nMonth - 1 ) << 5 );
|
||||
m_fDate |= ( ( nYear - 2009 ) << 9 );
|
||||
|
||||
#ifdef _DEBUG
|
||||
int nDbgDay, nDbgMonth, nDbgYear;
|
||||
GetDate( nDbgDay, nDbgMonth, nDbgYear );
|
||||
Assert( nDay == nDbgDay );
|
||||
Assert( nMonth == nDbgMonth );
|
||||
Assert( nYear == nDbgYear );
|
||||
#endif
|
||||
}
|
||||
|
||||
void CReplayTime::GetDate( int &nDay, int &nMonth, int &nYear ) const
|
||||
{
|
||||
nDay = 1 + ( m_fDate & 0x1F ); // Bits 0-4 for day
|
||||
nMonth = 1 + ( ( m_fDate >> 5 ) & 0x0F ); // Bits 5-8 for month
|
||||
nYear = 2009 + ( ( m_fDate >> 9 ) & 0x7F ); // Bits 9-15 for year
|
||||
|
||||
Assert( nDay >= 1 && nDay <= 31 );
|
||||
Assert( nMonth >= 1 && nMonth <= 12 );
|
||||
Assert( nYear >= 2009 && nYear <= 2136 );
|
||||
}
|
||||
|
||||
void CReplayTime::SetTime( int nHour, int nMin, int nSec )
|
||||
{
|
||||
Assert( nHour >= 0 && nHour <= 23 );
|
||||
Assert( nMin >= 0 && nMin <= 59 );
|
||||
Assert( nSec >= 0 && nSec <= 59 );
|
||||
|
||||
m_fTime = nHour;
|
||||
m_fTime |= ( ( nMin ) << 5 );
|
||||
m_fTime |= ( ( nSec ) << 11 );
|
||||
|
||||
#ifdef _DEBUG
|
||||
int nDbgHour, nDbgMin, nDbgSec;
|
||||
GetTime( nDbgHour, nDbgMin, nDbgSec );
|
||||
Assert( nHour == nDbgHour );
|
||||
Assert( nMin == nDbgMin );
|
||||
Assert( nSec == nDbgSec );
|
||||
#endif
|
||||
}
|
||||
|
||||
void CReplayTime::GetTime( int &nHour, int &nMin, int &nSec ) const
|
||||
{
|
||||
nHour = m_fTime & 0x1F; // Bits 0-4 for hour
|
||||
nMin = ( m_fTime >> 5 ) & 0x3F; // Bits 5-10 for min
|
||||
nSec = ( m_fTime >> 11 ) & 0x3F; // Bits 11-16 for sec
|
||||
|
||||
Assert( nHour >= 0 && nHour <= 23 );
|
||||
Assert( nMin >= 0 && nMin <= 59 );
|
||||
Assert( nSec >= 0 && nSec <= 59 );
|
||||
}
|
||||
|
||||
void CReplayTime::Read( KeyValues *pIn )
|
||||
{
|
||||
m_fDate = pIn->GetInt( "date" );
|
||||
m_fTime = pIn->GetInt( "time" );
|
||||
}
|
||||
|
||||
void CReplayTime::Write( KeyValues *pOut )
|
||||
{
|
||||
pOut->SetInt( "date", m_fDate );
|
||||
pOut->SetInt( "time", m_fTime );
|
||||
}
|
||||
|
||||
/*static*/ const wchar_t *CReplayTime::GetLocalizedMonth( vgui::ILocalize *pLocalize, int nMonth )
|
||||
{
|
||||
char szMonthKey[32]; // Get localized month
|
||||
|
||||
V_snprintf( szMonthKey, sizeof( szMonthKey ), "#Month_%i", nMonth );
|
||||
wchar_t *pResult = pLocalize->Find( szMonthKey );
|
||||
|
||||
return pResult ? pResult : L"";
|
||||
}
|
||||
|
||||
/*static*/ const wchar_t *CReplayTime::GetLocalizedDay( vgui::ILocalize *pLocalize, int nDay )
|
||||
{
|
||||
char szDay[8]; // Convert day to wide
|
||||
static wchar_t s_wDay[8];
|
||||
|
||||
V_snprintf( szDay, sizeof( szDay ), "%i", nDay );
|
||||
pLocalize->ConvertANSIToUnicode( szDay, s_wDay, sizeof( s_wDay ) );
|
||||
|
||||
return s_wDay;
|
||||
}
|
||||
|
||||
/*static*/ const wchar_t *CReplayTime::GetLocalizedYear( vgui::ILocalize *pLocalize, int nYear )
|
||||
{
|
||||
char szYear[8]; // Convert year to wide
|
||||
static wchar_t s_wYear[8];
|
||||
|
||||
V_snprintf( szYear, sizeof( szYear ), "%i", nYear );
|
||||
pLocalize->ConvertANSIToUnicode( szYear, s_wYear, sizeof( s_wYear ) );
|
||||
|
||||
return s_wYear;
|
||||
}
|
||||
|
||||
/*static*/ const wchar_t *CReplayTime::GetLocalizedTime( vgui::ILocalize *pLocalize, int nHour, int nMin, int nSec )
|
||||
{
|
||||
char szTime[16]; // Convert time to wide
|
||||
static wchar_t s_wTime[16];
|
||||
V_snprintf( szTime, sizeof( szTime ), "%i:%02i %s", nHour % 12, nMin, nHour < 12 ? "AM" : "PM" );
|
||||
pLocalize->ConvertANSIToUnicode( szTime, s_wTime, sizeof( s_wTime ) );
|
||||
|
||||
return s_wTime;
|
||||
}
|
||||
|
||||
/*static*/ const wchar_t *CReplayTime::GetLocalizedDate( vgui::ILocalize *pLocalize, const CReplayTime &t,
|
||||
bool bForceFullFormat/*=false*/ )
|
||||
{
|
||||
int nHour, nMin, nSec;
|
||||
int nDay, nMonth, nYear;
|
||||
t.GetTime( nHour, nMin, nSec );
|
||||
t.GetDate( nDay, nMonth, nYear );
|
||||
return GetLocalizedDate( pLocalize, nDay, nMonth, nYear, &nHour, &nMin, &nSec, bForceFullFormat );
|
||||
}
|
||||
|
||||
/*static*/ const wchar_t *CReplayTime::GetLocalizedDate( vgui::ILocalize *pLocalize, int nDay, int nMonth, int nYear,
|
||||
int *pHour/*=NULL*/, int *pMin/*=NULL*/, int *pSec/*=NULL*/,
|
||||
bool bForceFullFormat/*=false*/ )
|
||||
{
|
||||
static wchar_t s_wBuf[256];
|
||||
|
||||
// Is this collection for replays from today?
|
||||
time_t today;
|
||||
time( &today );
|
||||
tm *pNowTime = localtime( &today );
|
||||
bool bToday = ( pNowTime->tm_mday == nDay ) && ( pNowTime->tm_mon + 1 == nMonth ) && ( 1900 + pNowTime->tm_year == nYear );
|
||||
|
||||
// Yesterday?
|
||||
time_t yesterday = today - time_t( 86400 );
|
||||
tm *pYesterdayTime = localtime( &yesterday );
|
||||
bool bYesterday = ( pYesterdayTime->tm_mday == nDay ) && ( pYesterdayTime->tm_mon + 1 == nMonth ) && ( 1900 + pYesterdayTime->tm_year == nYear );
|
||||
|
||||
const wchar_t *pMonth = GetLocalizedMonth( pLocalize, nMonth );
|
||||
const wchar_t *pDay = GetLocalizedDay( pLocalize, nDay );
|
||||
const wchar_t *pYear = GetLocalizedYear( pLocalize, nYear );
|
||||
const wchar_t *pToday = pLocalize->Find( "#Replay_Today" );
|
||||
const wchar_t *pYesterday = pLocalize->Find( "#Replay_Yesterday" );
|
||||
|
||||
bool bTime = pHour && pMin && pSec;
|
||||
|
||||
// Include time in formatted string?
|
||||
if ( bTime )
|
||||
{
|
||||
const wchar_t *pTime = GetLocalizedTime( pLocalize, *pHour, *pMin, *pSec );
|
||||
|
||||
if ( bForceFullFormat || ( !bToday && !bYesterday ) )
|
||||
{
|
||||
pLocalize->ConstructString(
|
||||
s_wBuf,
|
||||
sizeof( s_wBuf ),
|
||||
pLocalize->Find( "#Replay_DateAndTime" ),
|
||||
4,
|
||||
pMonth, pDay, pYear, pTime
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
pLocalize->ConstructString(
|
||||
s_wBuf,
|
||||
sizeof( s_wBuf ),
|
||||
pLocalize->Find( "#Replay_SingleWordDateAndTime" ),
|
||||
2,
|
||||
bToday ? pToday : pYesterday,
|
||||
pTime
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !bToday && !bYesterday )
|
||||
{
|
||||
pLocalize->ConstructString(
|
||||
s_wBuf,
|
||||
sizeof( s_wBuf ),
|
||||
pLocalize->Find( "#Replay_Date" ),
|
||||
3,
|
||||
pMonth, pDay, pYear
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
V_wcsncpy( s_wBuf, bToday ? pToday : pYesterday, sizeof( s_wBuf ) );
|
||||
}
|
||||
}
|
||||
|
||||
return s_wBuf;
|
||||
}
|
||||
|
||||
/*static*/ const char *CReplayTime::FormatTimeString( int nSecs )
|
||||
{
|
||||
static int nWhichStr = 0;
|
||||
static const int nNumStrings = 2;
|
||||
static const int nStrLen = 32;
|
||||
static char s_szResult[nNumStrings][nStrLen];
|
||||
|
||||
char *pResult = s_szResult[ nWhichStr ];
|
||||
|
||||
int nSeconds = nSecs % 60;
|
||||
int nMins = nSecs / 60;
|
||||
int nHours = nMins / 60;
|
||||
nMins %= 60;
|
||||
|
||||
if ( nHours > 0 )
|
||||
{
|
||||
V_snprintf( pResult, nStrLen, "%i:%02i:%02i", nHours, nMins, nSeconds );
|
||||
}
|
||||
else
|
||||
{
|
||||
V_snprintf( pResult, nStrLen, "%02i:%02i", nMins, nSeconds );
|
||||
}
|
||||
|
||||
nWhichStr = ( nWhichStr + 1 ) % nNumStrings;
|
||||
|
||||
return pResult;
|
||||
}
|
||||
|
||||
/*static*/ const char *CReplayTime::FormatPreciseTimeString( float flSecs )
|
||||
{
|
||||
static int nWhichStr = 0;
|
||||
static const int nNumStrings = 2;
|
||||
static const int nStrLen = 32;
|
||||
static char s_szResult[nNumStrings][nStrLen];
|
||||
|
||||
char *pResult = s_szResult[ nWhichStr ];
|
||||
|
||||
int nSecs = (int)flSecs;
|
||||
int nMins = ( nSecs % 3600 ) / 60;
|
||||
int nSeconds = nSecs % 60;
|
||||
int nMilliseconds = (flSecs - (float)nSecs) * 10.0f;
|
||||
|
||||
V_snprintf( pResult, nStrLen, "%02i:%02i:%02i", nMins, nSeconds, nMilliseconds );
|
||||
|
||||
nWhichStr = ( nWhichStr + 1 ) % nNumStrings;
|
||||
|
||||
return pResult;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,130 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
//=======================================================================================//
|
||||
|
||||
#include "replay/replayutils.h"
|
||||
#include "dbg.h"
|
||||
#include "strtools.h"
|
||||
#include "qlimits.h"
|
||||
#include "filesystem.h"
|
||||
#include "replay/replaytime.h"
|
||||
#include "fmtstr.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
static char gs_szGameDir[MAX_OSPATH];
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
void Replay_GetFirstAvailableFilename( char *pDst, int nDstLen, const char *pIdealFilename, const char *pExt,
|
||||
const char *pFilePath, int nStartIndex )
|
||||
{
|
||||
// Strip extension from ideal filename
|
||||
char szIdealFilename[ MAX_OSPATH ];
|
||||
V_StripExtension( pIdealFilename, szIdealFilename, sizeof( szIdealFilename ) );
|
||||
|
||||
int i = nStartIndex;
|
||||
while ( 1 )
|
||||
{
|
||||
V_strncpy( pDst, szIdealFilename, nDstLen );
|
||||
V_strcat( pDst, Replay_va( "_%i%s", i, pExt ), nDstLen );
|
||||
|
||||
// Get a potential working path/filename
|
||||
CFmtStr fmtTestFilename(
|
||||
"%s%c%s",
|
||||
pFilePath,
|
||||
CORRECT_PATH_SEPARATOR,
|
||||
pDst
|
||||
);
|
||||
|
||||
// Make sure slashes are correct for platform
|
||||
V_FixSlashes( fmtTestFilename.Access() );
|
||||
|
||||
// Fix up double slashes
|
||||
V_FixDoubleSlashes( fmtTestFilename.Access() );
|
||||
|
||||
if ( !g_pFullFileSystem->FileExists( fmtTestFilename ) )
|
||||
break;
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
void Replay_ConstructReplayFilenameString( CUtlString &strOut, const char *pReplaySubDir, const char *pFilename, const char *pGameDir )
|
||||
{
|
||||
// Construct full filename
|
||||
strOut.Format( "%s%creplays%c%s%c%s", pGameDir,
|
||||
CORRECT_PATH_SEPARATOR, CORRECT_PATH_SEPARATOR, pReplaySubDir,
|
||||
CORRECT_PATH_SEPARATOR, pFilename
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
char *Replay_va( const char *format, ... )
|
||||
{
|
||||
va_list argptr;
|
||||
static char string[8][512];
|
||||
static int curstring = 0;
|
||||
|
||||
curstring = ( curstring + 1 ) % 8;
|
||||
|
||||
va_start (argptr, format);
|
||||
Q_vsnprintf( string[curstring], sizeof( string[curstring] ), format, argptr );
|
||||
va_end (argptr);
|
||||
|
||||
return string[curstring];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
void Replay_SetGameDir( const char *pGameDir )
|
||||
{
|
||||
V_strcpy( gs_szGameDir, pGameDir );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
const char *Replay_GetGameDir()
|
||||
{
|
||||
return gs_szGameDir;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
const char *Replay_GetBaseDir()
|
||||
{
|
||||
return Replay_va(
|
||||
"%s%creplays%c",
|
||||
Replay_GetGameDir(),
|
||||
CORRECT_PATH_SEPARATOR,
|
||||
CORRECT_PATH_SEPARATOR
|
||||
);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
void Replay_GetAutoName( wchar_t *pDest, int nDestSize, const char *pMapName )
|
||||
{
|
||||
// Get date/time
|
||||
CReplayTime now;
|
||||
now.InitDateAndTimeToNow();
|
||||
|
||||
// Convert map name to unicode
|
||||
wchar_t wszMapName[256];
|
||||
extern vgui::ILocalize *g_pVGuiLocalize;
|
||||
g_pVGuiLocalize->ConvertANSIToUnicode( pMapName, wszMapName, sizeof( wszMapName ) );
|
||||
|
||||
// Get localized date as string
|
||||
const wchar_t *pLocalizedDate = CReplayTime::GetLocalizedDate( g_pVGuiLocalize, now, true );
|
||||
|
||||
// Create title
|
||||
g_pVGuiLocalize->ConstructString( pDest, nDestSize, L"%s1: %s2", 2, wszMapName, pLocalizedDate );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,42 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
//=======================================================================================//
|
||||
|
||||
#include "replay/screenshot.h"
|
||||
#include "replay/replayutils.h"
|
||||
#include "replay/iclientreplaycontext.h"
|
||||
#include "KeyValues.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
bool CReplayScreenshot::Read( KeyValues *pIn )
|
||||
{
|
||||
m_nWidth = pIn->GetInt( "w" );
|
||||
m_nHeight = pIn->GetInt( "h" );
|
||||
V_strcpy_safe( m_szBaseFilename, pIn->GetString( "file", "" ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CReplayScreenshot::Write( KeyValues *pOut )
|
||||
{
|
||||
pOut->SetInt( "w", m_nWidth );
|
||||
pOut->SetInt( "h", m_nHeight );
|
||||
pOut->SetString( "file", m_szBaseFilename );
|
||||
}
|
||||
|
||||
const char *CReplayScreenshot::GetSubKeyTitle() const
|
||||
{
|
||||
return m_szBaseFilename;
|
||||
}
|
||||
|
||||
const char *CReplayScreenshot::GetPath() const
|
||||
{
|
||||
extern IClientReplayContext *g_pClientReplayContext;
|
||||
return Replay_va( "%s%s%c", g_pClientReplayContext->GetBaseDir(), SUBDIR_SCREENSHOTS, CORRECT_PATH_SEPARATOR );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user