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.
346 lines
11 KiB
346 lines
11 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
//=======================================================================================// |
|
|
|
#include "cl_screenshotmanager.h" |
|
#include "convar.h" |
|
#include "replaysystem.h" |
|
#include "netmessages.h" |
|
#include "cl_replaymanager.h" |
|
#include "cl_sessionblockdownloader.h" |
|
#include "cl_recordingsession.h" |
|
#include "cl_renderqueue.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
//---------------------------------------------------------------------------------------- |
|
|
|
extern ConVar replay_postdeathrecordtime; |
|
|
|
//---------------------------------------------------------------------------------------- |
|
|
|
CON_COMMAND( save_replay, "Save a replay of the current life if possible." ) |
|
{ |
|
// Is the user running a listen server? |
|
if ( g_pEngineClient->IsListenServer() ) |
|
{ |
|
Replay_HudMsg( "#Replay_NoListenServer", "replay\\record_fail.wav", true ); |
|
return; |
|
} |
|
|
|
// Replay enabled on the server? |
|
if ( !g_pReplay->IsReplayEnabled() ) |
|
{ |
|
Replay_HudMsg( "#Replay_NotEnabled", "replay\\record_fail.wav", true ); |
|
return; |
|
} |
|
|
|
// Are we recording? |
|
if ( !g_pReplay->IsRecording() ) |
|
{ |
|
Replay_HudMsg( "#Replay_NotRecording", "replay\\record_fail.wav", true ); |
|
return; |
|
} |
|
|
|
// Is replay disabled on the client? |
|
if ( g_pClientReplayContextInternal->IsClientSideReplayDisabled() ) |
|
{ |
|
Replay_HudMsg( "#Replay_ClientSideDisabled", NULL, true ); |
|
return; |
|
} |
|
|
|
// Get the replay for the current life |
|
CReplay *pReplayForCurrentLife = CL_GetReplayManager()->m_pReplayThisLife; |
|
|
|
// Already saved this replay? |
|
if ( !pReplayForCurrentLife || pReplayForCurrentLife->m_bRequestedByUser || pReplayForCurrentLife->m_bSaved ) |
|
{ |
|
Replay_HudMsg( "#Replay_AlreadySaved", "replay\\record_fail.wav" ); |
|
return; |
|
} |
|
|
|
// Take a screenshot and write it to disk if one hasn't been taken already |
|
if ( !pReplayForCurrentLife->GetScreenshotCount() ) |
|
{ |
|
CaptureScreenshotParams_t params; |
|
V_memset( ¶ms, 0, sizeof( params ) ); |
|
params.m_flDelay = 0.0f; |
|
params.m_bPrimary = true; |
|
CL_GetScreenshotManager()->CaptureScreenshot( params ); |
|
} |
|
|
|
// Send a message to the server, regardless of whether the player is alive or dead, requesting |
|
// that a demo be written. Format a file name with the client's steam id and a timestamp |
|
// (gpGlobals->tickcount). |
|
CLC_SaveReplay msgSaveReplay; |
|
g_pEngineClient->GetNetChannel()->SendNetMsg( msgSaveReplay, true ); |
|
|
|
// Get the session |
|
CClientRecordingSession *pSession = CL_CastSession( CL_GetRecordingSessionManager()->Find( pReplayForCurrentLife->m_hSession ) ); |
|
if ( !pSession ) |
|
{ |
|
AssertMsg( 0, "Replay points to a non-existent session - should never happen!" ); |
|
CL_GetErrorSystem()->AddErrorFromTokenName( "#Replay_ReplayBadSession" ); |
|
return; |
|
} |
|
|
|
// Replay for current life is complete (ie, player is dead and replay is ready to be committed) |
|
if ( pReplayForCurrentLife->m_bComplete ) |
|
{ |
|
CL_GetReplayManager()->CommitPendingReplayAndBeginDownload(); |
|
} |
|
else |
|
{ |
|
// Mark the replay as requested by the user, so we can commit automatically as soon as |
|
// the replay is complete (ie when the player dies, etc.). |
|
pReplayForCurrentLife->m_bRequestedByUser = true; |
|
} |
|
|
|
// Cache replay pointer in owning session |
|
pSession->CacheReplay( pReplayForCurrentLife ); |
|
|
|
// Make sure downloading is enabled |
|
pSession->EnsureDownloadingEnabled(); |
|
|
|
// Add the new entry to the replay browser |
|
g_pClient->OnSaveReplay( pReplayForCurrentLife->GetHandle(), true ); |
|
} |
|
|
|
//---------------------------------------------------------------------------------------- |
|
|
|
CON_COMMAND( replay_add_fake_replays, "Adds a set of fake replays" ) |
|
{ |
|
if ( args.ArgC() < 2 ) |
|
{ |
|
DevMsg( "Use \'replay_add_fake_replays\' <num fake replays to add> <today only>\n" ); |
|
return; |
|
} |
|
|
|
// bool bTodayOnly = args.ArgC() >= 3 && args[2][0] == '1'; |
|
for ( int i = 0; i < atoi(args[1]); ++i ) |
|
{ |
|
// TODO: |
|
} |
|
} |
|
|
|
//---------------------------------------------------------------------------------------- |
|
|
|
CON_COMMAND_F( replay_confirmquit, "Make sure all replays are rendered before quitting", FCVAR_HIDDEN | FCVAR_DONTRECORD ) |
|
{ |
|
// TODO: Check to see if any replays are downloading - warn user. If user wants to |
|
// quit anyway, make sure to set any blocks to not downloaded, save, and delete any |
|
// files that were only partially downloaded. |
|
|
|
// Unrendered replays? Display the quit confirmation dialog with the option to render all and quit |
|
if ( CL_GetReplayManager()->GetUnrenderedReplayCount() > 0 && g_pClient->OnConfirmQuit() ) |
|
{ |
|
// Play a sound. |
|
g_pClient->PlaySound( "replay\\confirmquit.wav" ); |
|
} |
|
else |
|
{ |
|
g_pEngine->Cbuf_AddText( "quit" ); |
|
g_pEngine->Cbuf_AddText( "\n" ); |
|
} |
|
} |
|
|
|
//---------------------------------------------------------------------------------------- |
|
|
|
CON_COMMAND_F( replay_deleteclientreplays, "Deletes all replays from client replay history, as well as all files associated with each replay.", FCVAR_DONTRECORD ) |
|
{ |
|
CUtlVector< ReplayHandle_t > vecReplayHandles; |
|
FOR_EACH_REPLAY( i ) |
|
{ |
|
vecReplayHandles.AddToTail( GET_REPLAY_AT( i )->GetHandle() ); |
|
} |
|
|
|
FOR_EACH_VEC( vecReplayHandles, i ) |
|
{ |
|
CL_GetReplayManager()->DeleteReplay( vecReplayHandles[ i ], true ); |
|
} |
|
} |
|
|
|
//---------------------------------------------------------------------------------------- |
|
|
|
CON_COMMAND_F( replay_removeclientreplay, "Remove the replay at the given index.", FCVAR_DONTRECORD ) |
|
{ |
|
if ( args.ArgC() != 2 ) |
|
{ |
|
Msg( "Not enough parameters.\n" ); |
|
return; |
|
} |
|
|
|
CL_GetReplayManager()->DeleteReplay( atoi(args[ 1 ]), true ); |
|
} |
|
|
|
//---------------------------------------------------------------------------------------- |
|
|
|
CON_COMMAND_F( replay_printclientreplays, "Prints out all client replay info", FCVAR_DONTRECORD ) |
|
{ |
|
FOR_EACH_REPLAY( i ) |
|
{ |
|
const CReplay *pReplay = GET_REPLAY_AT( i ); |
|
if ( !pReplay ) |
|
continue; |
|
|
|
int nMonth, nDay, nYear; |
|
pReplay->m_RecordTime.GetDate( nDay, nMonth, nYear ); |
|
|
|
int nHour, nMin, nSec; |
|
pReplay->m_RecordTime.GetTime( nHour, nMin, nSec ); |
|
|
|
int nSpawnTick = pReplay->m_nSpawnTick; |
|
int nDeathTick = pReplay->m_nDeathTick; |
|
|
|
// TODO: All of this should go into a virtual function in CReplay, rather than some here and some in DumpGameSpecificData() |
|
char szTitle[MAX_REPLAY_TITLE_LENGTH]; |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( pReplay->m_wszTitle, szTitle, sizeof( szTitle ) ); |
|
Msg( "replay %i: \"%s\"\n", i, szTitle ); |
|
Msg( " handle: %i\n", pReplay->GetHandle() ); |
|
Msg( " spawn/death tick: %i / %i\n", nSpawnTick, nDeathTick ); |
|
Msg( " date: %i/%i/%i\n", nMonth, nDay, nYear ); |
|
Msg( " time: %i:%i:%i\n", nHour, nMin, nSec ); |
|
Msg( " map: %s\n", pReplay->m_szMapName ); |
|
|
|
CClientRecordingSession *pSession = CL_CastSession( CL_GetRecordingSessionManager()->FindSession( pReplay->m_hSession ) ); |
|
const char *pSessionName = pSession ? pSession->m_strName.Get() : NULL; |
|
Msg( " session name: %s\n", pSessionName ? pSessionName : "" ); |
|
|
|
if ( pSession ) |
|
{ |
|
Msg( " last block downloaded: %i\n", pSession->GetGreatestConsecutiveBlockDownloaded() ); |
|
Msg( " last block to download: %i\n", pSession->GetLastBlockToDownload() ); |
|
} |
|
|
|
int nScreenshotCount = pReplay->GetScreenshotCount(); |
|
Msg( "\n" ); |
|
Msg( " # screenshots: %i\n", nScreenshotCount ); |
|
Msg( " session handle: %i\n", (int)pReplay->m_hSession ); |
|
|
|
for ( int i = 0; i < nScreenshotCount; ++i ) |
|
{ |
|
const CReplayScreenshot *pScreenshot = pReplay->GetScreenshot( i ); |
|
Msg( " screenshot %i:\n", i ); |
|
Msg( " dimensions: w=%i, h=%i\n", pScreenshot->m_nWidth, pScreenshot->m_nHeight ); |
|
Msg( " base filename: %s\n", pScreenshot->m_szBaseFilename ); |
|
} |
|
|
|
int nPerfCount = pReplay->GetPerformanceCount(); |
|
Msg( "\n" ); |
|
Msg( "# performances: %i\n", nPerfCount ); |
|
for ( int i = 0; i < nPerfCount; ++i ) |
|
{ |
|
const CReplayPerformance *pCurPerformance = pReplay->GetPerformance( i ); |
|
g_pVGuiLocalize->ConvertUnicodeToANSI( pCurPerformance->m_wszTitle, szTitle, sizeof( szTitle ) ); |
|
Msg( " performance %i:\n", i ); |
|
Msg( " title: %s\n", szTitle ); |
|
Msg( " ticks: in=%i out=%i\n", pCurPerformance->m_nTickIn, pCurPerformance->m_nTickOut ); |
|
Msg( " filename: %s\n", pCurPerformance->m_szBaseFilename ); |
|
} |
|
Msg( "\n" ); |
|
|
|
pReplay->DumpGameSpecificData(); |
|
|
|
// Print replay status |
|
const char *pStatus; |
|
switch ( pReplay->m_nStatus ) |
|
{ |
|
case CReplay::REPLAYSTATUS_INVALID: pStatus = "invalid"; break; |
|
case CReplay::REPLAYSTATUS_DOWNLOADPHASE: pStatus = "download phase"; break; |
|
case CReplay::REPLAYSTATUS_READYTOCONVERT: pStatus = "ready to convert"; break; |
|
case CReplay::REPLAYSTATUS_RENDERING: pStatus = "rendering"; break; |
|
case CReplay::REPLAYSTATUS_RENDERED: pStatus = "rendered"; break; |
|
case CReplay::REPLAYSTATUS_ERROR: pStatus = "error"; break; |
|
default: pStatus = ""; |
|
} |
|
Msg( " status: %s\n\n\n", pStatus ); |
|
} |
|
} |
|
|
|
//---------------------------------------------------------------------------------------- |
|
|
|
CON_COMMAND_F( replay_renderpause, "Pause Replay rendering.", FCVAR_DONTRECORD ) |
|
{ |
|
if ( !CL_GetMovieManager()->IsRendering() ) |
|
return; |
|
|
|
if ( g_pReplayDemoPlayer->IsReplayPaused() ) |
|
{ |
|
Msg( "Replay rendering already paused.\n" ); |
|
return; |
|
} |
|
|
|
// Pause playback |
|
g_pReplayDemoPlayer->PauseReplay(); |
|
} |
|
|
|
//---------------------------------------------------------------------------------------- |
|
|
|
CON_COMMAND_F( replay_renderunpause, "Unpause Replay rendering.", FCVAR_DONTRECORD ) |
|
{ |
|
if ( !CL_GetMovieManager()->IsRendering() ) |
|
return; |
|
|
|
if ( !g_pReplayDemoPlayer->IsReplayPaused() ) |
|
{ |
|
Msg( "Replay rendering not paused.\n" ); |
|
return; |
|
} |
|
|
|
// Unpause |
|
g_pReplayDemoPlayer->ResumeReplay(); |
|
} |
|
|
|
//---------------------------------------------------------------------------------------- |
|
|
|
CON_COMMAND_F( replay_printqueuedtakes, "Print a list of takes queued for rendering.", FCVAR_DONTRECORD ) |
|
{ |
|
const int nCount = CL_GetRenderQueue()->GetCount(); |
|
if ( !nCount ) |
|
{ |
|
ConMsg( "No takes queued for render.\n" ); |
|
return; |
|
} |
|
|
|
ConMsg( "Takes queued for render:\n" ); |
|
ConMsg( " %65s%65s\n", "Replay Name", "Take Name" ); |
|
for ( int i = 0; i < nCount; ++i ) |
|
{ |
|
ReplayHandle_t hReplay; |
|
int iPerf; |
|
CL_GetRenderQueue()->GetEntryData( i, &hReplay, &iPerf ); |
|
const CReplay *pReplay = CL_GetReplayManager()->GetReplay( hReplay ); |
|
if ( !pReplay ) |
|
continue; |
|
|
|
char szTakeName[MAX_REPLAY_TITLE_LENGTH]; |
|
|
|
if ( iPerf == -1 ) |
|
{ |
|
V_strcpy( szTakeName, "original" ); |
|
} |
|
else |
|
{ |
|
const CReplayPerformance *pPerformance = pReplay->GetPerformance( iPerf ); |
|
if ( !pPerformance ) |
|
continue; |
|
V_wcstostr( pPerformance->m_wszTitle, -1, szTakeName, sizeof( szTakeName ) ); |
|
} |
|
|
|
char szReplayTitle[MAX_REPLAY_TITLE_LENGTH]; |
|
V_wcstostr( pReplay->m_wszTitle, -1, szReplayTitle, sizeof( szReplayTitle ) ); |
|
|
|
ConMsg( " %02i:%65s%65s\n", i, szReplayTitle, szTakeName ); |
|
} |
|
} |
|
|
|
//---------------------------------------------------------------------------------------- |
|
|
|
CON_COMMAND_F( replay_clearqueuedtakes, "Clear takes from render queue.", FCVAR_DONTRECORD ) |
|
{ |
|
CL_GetRenderQueue()->Clear(); |
|
ConMsg( "Cleared.\n" ); |
|
} |
|
|
|
//----------------------------------------------------------------------------------------
|
|
|