summaryrefslogtreecommitdiff
path: root/replay/sv_commands.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /replay/sv_commands.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'replay/sv_commands.cpp')
-rw-r--r--replay/sv_commands.cpp208
1 files changed, 208 insertions, 0 deletions
diff --git a/replay/sv_commands.cpp b/replay/sv_commands.cpp
new file mode 100644
index 0000000..d2fd72e
--- /dev/null
+++ b/replay/sv_commands.cpp
@@ -0,0 +1,208 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//=======================================================================================//
+
+#include "replaysystem.h"
+#include "sv_sessionrecorder.h"
+#include "utlbuffer.h"
+#include "sessioninfoheader.h"
+#include "sv_fileservercleanup.h"
+#include "sv_publishtest.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//----------------------------------------------------------------------------------------
+
+#define ENSURE_DEDICATED() if ( !g_pEngine->IsDedicated() ) return;
+
+//----------------------------------------------------------------------------------------
+
+CON_COMMAND( replay_record, "Starts Replay demo recording." )
+{
+ ENSURE_DEDICATED();
+ SV_GetSessionRecorder()->StartRecording();
+}
+
+//----------------------------------------------------------------------------------------
+
+CON_COMMAND( replay_stoprecord, "Stop Replay demo recording." )
+{
+ ENSURE_DEDICATED();
+ g_pReplay->SV_EndRecordingSession();
+}
+
+//----------------------------------------------------------------------------------------
+
+CON_COMMAND( replay_docleanup, "Deletes stale session data from the fileserver. \"replay_docleanup force\" will remove all replay session data." )
+{
+ ENSURE_DEDICATED();
+
+ bool bForceCleanAll = false;
+ if ( args.ArgC() == 2 )
+ {
+ if ( !V_stricmp( args[1], "force" ) )
+ {
+ bForceCleanAll = true;
+ }
+ else
+ {
+ ConMsg( "\n ** ERROR: '%s' is not a valid paramter - use 'force' to force clean all replay session data.\n\n", args[1] );
+ return;
+ }
+ }
+
+ if ( !SV_DoFileserverCleanup( bForceCleanAll, g_pBlockSpewer ) )
+ {
+ Msg( "No demos were deleted.\n" );
+ }
+}
+
+//----------------------------------------------------------------------------------------
+
+CON_COMMAND_F( replay_dopublishtest, "Do a replay publish test using the current setup.", FCVAR_DONTRECORD )
+{
+ ENSURE_DEDICATED();
+
+ g_pBlockSpewer->PrintBlockStart();
+ SV_DoTestPublish();
+ g_pBlockSpewer->PrintBlockEnd();
+}
+
+//----------------------------------------------------------------------------------------
+
+void PrintSessionInfo( const char *pFilename )
+{
+ CUtlBuffer buf;
+ if ( !g_pFullFileSystem->ReadFile( pFilename, NULL, buf ) )
+ {
+ Msg( "Failed to read file, \"%s\"\n", pFilename );
+ return;
+ }
+
+ int nFileSize = buf.TellPut();
+
+ SessionInfoHeader_t header;
+ if ( !ReadSessionInfoHeader( buf.Base(), nFileSize, header ) )
+ {
+ Msg( "Failed to read header information.\n" );
+ return;
+ }
+
+ char szDigestStr[33];
+ V_binarytohex( header.m_aHash, sizeof( header.m_aHash ), szDigestStr, sizeof( szDigestStr ) );
+
+ Msg( "\n\theader:\n" );
+ Msg( "\n" );
+ Msg( "\t%27s: %u\n", "version", header.m_uVersion );
+ Msg( "\t%27s: %s\n", "session name", header.m_szSessionName );
+ Msg( "\t%27s: %s\n", "currently recording?", header.m_bRecording ? "yes" : "no" );
+ Msg( "\t%27s: %i\n", "# blocks", header.m_nNumBlocks );
+ Msg( "\t%27s: %s\n", "compressor", GetCompressorNameSafe( header.m_nCompressorType ) );
+ Msg( "\t%27s: %s\n", "md5 digest", szDigestStr );
+ Msg( "\t%27s: %u bytes\n", "payload size (compressed)", header.m_uPayloadSize );
+ Msg( "\t%27s: %u bytes\n", "payload size (uncompressed)", header.m_uPayloadSizeUC );
+ Msg( "\n" );
+
+ const uint8 *pPayload = (uint8 *)buf.Base() + sizeof( SessionInfoHeader_t );
+ uint32 uUncompressedPayloadSize = header.m_uPayloadSizeUC;
+ if ( !g_pEngine->MD5_HashBuffer( header.m_aHash, (const uint8 *)pPayload, header.m_uPayloadSize, NULL ) )
+ {
+ Msg( "Data validation failed.\n" );
+ return;
+ }
+
+ const uint8 *pUncompressedPayload;
+ bool bFreeUncompressedPayload = true;
+
+ if ( header.m_nCompressorType == COMPRESSORTYPE_INVALID )
+ {
+ // The payload is already uncompressed - don't free, since this buffer was allocated by the CUtlBuffer "buf"
+ pUncompressedPayload = pPayload;
+ bFreeUncompressedPayload = false;
+ }
+ else
+ {
+ if ( uUncompressedPayloadSize != header.m_uPayloadSizeUC )
+ {
+ Msg( "Decompressed to a different size (%u) than specified by header (%u)\n", uUncompressedPayloadSize, header.m_uPayloadSizeUC );
+ return;
+ }
+
+ ICompressor *pCompressor = CreateCompressor( header.m_nCompressorType );
+ if ( !pCompressor )
+ {
+ Msg( "Failed to create compressor.\n" );
+ return;
+ }
+
+ pUncompressedPayload = new uint8[ uUncompressedPayloadSize ];
+ if ( !pUncompressedPayload )
+ {
+ Msg( "Failed to allocate uncompressed payload.\n" );
+ delete [] pCompressor;
+ return;
+ }
+
+ pCompressor->Decompress( (char *)pUncompressedPayload, &uUncompressedPayloadSize, (const char *)pPayload, header.m_uPayloadSize );
+
+ delete pCompressor;
+ }
+
+ if ( uUncompressedPayloadSize <= MIN_SESSION_INFO_PAYLOAD_SIZE )
+ {
+ Msg( "Uncompressed payload not large enough to read a single block.\n" );
+ }
+ else
+ {
+ RecordingSessionBlockSpec_t DummyBlock;
+ CUtlBuffer bufPayload( pUncompressedPayload, uUncompressedPayloadSize, CUtlBuffer::READ_ONLY );
+
+ Msg( "\n\tblocks:\n\n" );
+ Msg( "\t index status MD5 compressor size (uncompressed) size (compressed)\n" );
+
+ bool bBlockReadFailed = false;
+ for ( int i = 0; i < header.m_nNumBlocks; ++i )
+ {
+ // Attempt to read the current block from the buffer
+ bufPayload.Get( &DummyBlock, sizeof( DummyBlock ) );
+ if ( !bufPayload.IsValid() )
+ {
+ bBlockReadFailed = true;
+ break;
+ }
+
+ V_binarytohex( DummyBlock.m_aHash, sizeof( DummyBlock.m_aHash ), szDigestStr, sizeof( szDigestStr ) );
+
+ Msg( "\t %5i", DummyBlock.m_iReconstruction );
+ Msg( "%20s", CBaseRecordingSessionBlock::GetRemoteStatusStringSafe( (CBaseRecordingSessionBlock::RemoteStatus_t)DummyBlock.m_uRemoteStatus ) );
+ Msg( "%35s", szDigestStr );
+ Msg( "%8s", GetCompressorNameSafe( (CompressorType_t)DummyBlock.m_nCompressorType ) );
+ Msg( "%20u", DummyBlock.m_uFileSize );
+ Msg( "%20u", DummyBlock.m_uUncompressedSize );
+ Msg( "\n" );
+ }
+ }
+
+ Msg( "\n" );
+
+ if ( bFreeUncompressedPayload )
+ {
+ delete [] pUncompressedPayload;
+ }
+}
+
+CON_COMMAND_F( replay_printsessioninfo, "Print session info", FCVAR_DONTRECORD )
+{
+ ENSURE_DEDICATED();
+
+ if ( args.ArgC() != 2 )
+ {
+ Msg( "Usage: replay_printsessioninfo <full path and filename>\n" );
+ return;
+ }
+
+ PrintSessionInfo( args[1] );
+}
+
+//----------------------------------------------------------------------------------------