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/cl_commands.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'replay/cl_commands.cpp')
| -rw-r--r-- | replay/cl_commands.cpp | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/replay/cl_commands.cpp b/replay/cl_commands.cpp new file mode 100644 index 0000000..cd7975d --- /dev/null +++ b/replay/cl_commands.cpp @@ -0,0 +1,346 @@ +//========= 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" ); +} + +//---------------------------------------------------------------------------------------- |