mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-09-20 20:46:03 +08:00
Update from SDK 2013
This commit is contained in:

committed by
Nicholas Hastings

parent
6d5c024820
commit
94b660e16e
@ -1,361 +1,367 @@
|
||||
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
#include "cbase.h"
|
||||
#include "isaverestore.h"
|
||||
#include "env_debughistory.h"
|
||||
#include "tier0/vprof.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// Number of characters worth of debug to use per history category
|
||||
#define DEBUG_HISTORY_VERSION 6
|
||||
#define DEBUG_HISTORY_FIRST_VERSIONED 5
|
||||
#define MAX_DEBUG_HISTORY_LINE_LENGTH 256
|
||||
#define MAX_DEBUG_HISTORY_LENGTH (1000 * MAX_DEBUG_HISTORY_LINE_LENGTH)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Stores debug history in savegame files for debugging reference
|
||||
//-----------------------------------------------------------------------------
|
||||
class CDebugHistory : public CBaseEntity
|
||||
{
|
||||
DECLARE_CLASS( CDebugHistory, CBaseEntity );
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
|
||||
void Spawn();
|
||||
void AddDebugHistoryLine( int iCategory, const char *szLine );
|
||||
void ClearHistories( void );
|
||||
void DumpDebugHistory( int iCategory );
|
||||
|
||||
int Save( ISave &save );
|
||||
int Restore( IRestore &restore );
|
||||
|
||||
private:
|
||||
char m_DebugLines[MAX_HISTORY_CATEGORIES][MAX_DEBUG_HISTORY_LENGTH];
|
||||
char *m_DebugLineEnd[MAX_HISTORY_CATEGORIES];
|
||||
};
|
||||
|
||||
BEGIN_DATADESC( CDebugHistory )
|
||||
//DEFINE_FIELD( m_DebugLines, FIELD_CHARACTER ), // Not saved because we write it out manually
|
||||
//DEFINE_FIELD( m_DebugLineEnd, FIELD_CHARACTER ),
|
||||
END_DATADESC()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_debughistory, CDebugHistory );
|
||||
|
||||
// The handle to the debug history singleton. Created on first access via GetDebugHistory.
|
||||
static CHandle< CDebugHistory > s_DebugHistory;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Spawn
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDebugHistory::Spawn()
|
||||
{
|
||||
BaseClass::Spawn();
|
||||
|
||||
#ifdef DISABLE_DEBUG_HISTORY
|
||||
UTIL_Remove( this );
|
||||
#else
|
||||
if ( g_pGameRules && g_pGameRules->IsMultiplayer() )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "DEBUG HISTORY IS ENABLED. Disable before release (in env_debughistory.h).\n" );
|
||||
}
|
||||
#endif
|
||||
|
||||
ClearHistories();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDebugHistory::AddDebugHistoryLine( int iCategory, const char *szLine )
|
||||
{
|
||||
if ( iCategory < 0 || iCategory >= MAX_HISTORY_CATEGORIES )
|
||||
{
|
||||
Warning("Attempted to add a debughistory line to category %d. Valid categories are %d to %d.\n", iCategory, 0, (MAX_HISTORY_CATEGORIES-1) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't do debug history before the singleton is properly set up.
|
||||
if ( !m_DebugLineEnd[iCategory] )
|
||||
return;
|
||||
|
||||
const char *pszRemaining = szLine;
|
||||
int iCharsToWrite = strlen( pszRemaining ) + 1; // Add 1 so that we copy the null terminator
|
||||
|
||||
// Clip the line if it's too long. Wasteful doing it this way, but keeps code below nice & simple.
|
||||
char szTmpBuffer[MAX_DEBUG_HISTORY_LINE_LENGTH];
|
||||
if ( iCharsToWrite > MAX_DEBUG_HISTORY_LINE_LENGTH)
|
||||
{
|
||||
memcpy( szTmpBuffer, szLine, sizeof(szTmpBuffer) );
|
||||
szTmpBuffer[MAX_DEBUG_HISTORY_LINE_LENGTH-1] = '\0';
|
||||
pszRemaining = szTmpBuffer;
|
||||
iCharsToWrite = MAX_DEBUG_HISTORY_LINE_LENGTH;
|
||||
}
|
||||
|
||||
while ( iCharsToWrite )
|
||||
{
|
||||
int iCharsLeftBeforeLoop = sizeof(m_DebugLines[iCategory]) - (m_DebugLineEnd[iCategory] - m_DebugLines[iCategory]);
|
||||
|
||||
// Write into the buffer
|
||||
int iWrote = MIN( iCharsToWrite, iCharsLeftBeforeLoop );
|
||||
memcpy( m_DebugLineEnd[iCategory], pszRemaining, iWrote );
|
||||
m_DebugLineEnd[iCategory] += iWrote;
|
||||
pszRemaining += iWrote;
|
||||
|
||||
// Did we loop?
|
||||
if ( iWrote == iCharsLeftBeforeLoop )
|
||||
{
|
||||
m_DebugLineEnd[iCategory] = m_DebugLines[iCategory];
|
||||
}
|
||||
|
||||
iCharsToWrite -= iWrote;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDebugHistory::DumpDebugHistory( int iCategory )
|
||||
{
|
||||
if ( iCategory < 0 || iCategory >= MAX_HISTORY_CATEGORIES )
|
||||
{
|
||||
Warning("Attempted to dump a history for category %d. Valid categories are %d to %d.\n", iCategory, 0, (MAX_HISTORY_CATEGORIES-1) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the start of the oldest whole debug line.
|
||||
const char *pszLine = m_DebugLineEnd[iCategory] + 1;
|
||||
if ( (size_t)(pszLine - m_DebugLines[iCategory]) >= sizeof(m_DebugLines[iCategory]) )
|
||||
{
|
||||
pszLine = m_DebugLines[iCategory];
|
||||
}
|
||||
|
||||
// Are we at the start of a line? If there's a null terminator before us, then we're good to go.
|
||||
while ( (!( pszLine == m_DebugLines[iCategory] && *(m_DebugLines[iCategory]+sizeof(m_DebugLines[iCategory])-1) == '\0' ) &&
|
||||
!( pszLine != m_DebugLines[iCategory] && *(pszLine-1) == '\0' ))
|
||||
|| *pszLine == '\0' )
|
||||
{
|
||||
pszLine++;
|
||||
|
||||
// Have we looped?
|
||||
if ( (size_t)(pszLine - m_DebugLines[iCategory]) >= sizeof(m_DebugLines[iCategory]) )
|
||||
{
|
||||
pszLine = m_DebugLines[iCategory];
|
||||
}
|
||||
|
||||
if ( pszLine == m_DebugLineEnd[iCategory] )
|
||||
{
|
||||
// We looped through the entire history, and found nothing.
|
||||
Msg( "Debug History of Category %d is EMPTY\n", iCategory );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Now print everything up till the end
|
||||
char szMsgBuffer[MAX_DEBUG_HISTORY_LINE_LENGTH];
|
||||
char *pszMsg = szMsgBuffer;
|
||||
Msg( "Starting Debug History Dump of Category %d\n", iCategory );
|
||||
while ( pszLine != m_DebugLineEnd[iCategory] )
|
||||
{
|
||||
*pszMsg = *pszLine;
|
||||
if ( *pszLine == '\0' )
|
||||
{
|
||||
if ( szMsgBuffer[0] != '\0' )
|
||||
{
|
||||
// Found a full line, so print it
|
||||
Msg( szMsgBuffer );
|
||||
}
|
||||
|
||||
// Clear the buffer
|
||||
pszMsg = szMsgBuffer;
|
||||
*pszMsg = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
pszMsg++;
|
||||
}
|
||||
|
||||
pszLine++;
|
||||
|
||||
// Have we looped?
|
||||
if ( (size_t)(pszLine - m_DebugLines[iCategory]) >= sizeof(m_DebugLines[iCategory]) )
|
||||
{
|
||||
pszLine = m_DebugLines[iCategory];
|
||||
}
|
||||
}
|
||||
Msg("Ended Debug History Dump of Category %d\n", iCategory );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDebugHistory::ClearHistories( void )
|
||||
{
|
||||
for ( int i = 0; i < MAX_HISTORY_CATEGORIES; i++ )
|
||||
{
|
||||
memset( m_DebugLines[i], 0, sizeof(m_DebugLines[i]) );
|
||||
m_DebugLineEnd[i] = m_DebugLines[i];
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CDebugHistory::Save( ISave &save )
|
||||
{
|
||||
int iVersion = DEBUG_HISTORY_VERSION;
|
||||
save.WriteInt( &iVersion );
|
||||
int iMaxCategorys = MAX_HISTORY_CATEGORIES;
|
||||
save.WriteInt( &iMaxCategorys );
|
||||
for ( int iCategory = 0; iCategory < MAX_HISTORY_CATEGORIES; iCategory++ )
|
||||
{
|
||||
int iEnd = m_DebugLineEnd[iCategory] - m_DebugLines[iCategory];
|
||||
save.WriteInt( &iEnd );
|
||||
save.WriteData( m_DebugLines[iCategory], MAX_DEBUG_HISTORY_LENGTH );
|
||||
}
|
||||
|
||||
return BaseClass::Save(save);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CDebugHistory::Restore( IRestore &restore )
|
||||
{
|
||||
ClearHistories();
|
||||
|
||||
int iVersion = restore.ReadInt();
|
||||
|
||||
if ( iVersion >= DEBUG_HISTORY_FIRST_VERSIONED )
|
||||
{
|
||||
int iMaxCategorys = restore.ReadInt();
|
||||
for ( int iCategory = 0; iCategory < MIN(iMaxCategorys,MAX_HISTORY_CATEGORIES); iCategory++ )
|
||||
{
|
||||
int iEnd = restore.ReadInt();
|
||||
m_DebugLineEnd[iCategory] = m_DebugLines[iCategory] + iEnd;
|
||||
restore.ReadData( m_DebugLines[iCategory], sizeof(m_DebugLines[iCategory]), 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int iMaxCategorys = iVersion;
|
||||
for ( int iCategory = 0; iCategory < MIN(iMaxCategorys,MAX_HISTORY_CATEGORIES); iCategory++ )
|
||||
{
|
||||
int iEnd = restore.ReadInt();
|
||||
m_DebugLineEnd[iCategory] = m_DebugLines[iCategory] + iEnd;
|
||||
restore.ReadData( m_DebugLines[iCategory], sizeof(m_DebugLines[iCategory]), 0 );
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::Restore(restore);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Singleton debug history. Created by first usage.
|
||||
//-----------------------------------------------------------------------------
|
||||
CDebugHistory *GetDebugHistory()
|
||||
{
|
||||
#ifdef DISABLE_DEBUG_HISTORY
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
if ( g_pGameRules && g_pGameRules->IsMultiplayer() )
|
||||
return NULL;
|
||||
|
||||
if ( s_DebugHistory == NULL )
|
||||
{
|
||||
CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, "env_debughistory" );
|
||||
if ( pEnt )
|
||||
{
|
||||
s_DebugHistory = dynamic_cast<CDebugHistory*>(pEnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_DebugHistory = ( CDebugHistory * )CreateEntityByName( "env_debughistory" );
|
||||
if ( s_DebugHistory )
|
||||
{
|
||||
s_DebugHistory->Spawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert( s_DebugHistory );
|
||||
return s_DebugHistory;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void AddDebugHistoryLine( int iCategory, const char *pszLine )
|
||||
{
|
||||
#ifdef DISABLE_DEBUG_HISTORY
|
||||
return;
|
||||
#else
|
||||
if ( g_pGameRules && g_pGameRules->IsMultiplayer() )
|
||||
return;
|
||||
|
||||
if ( !GetDebugHistory() )
|
||||
{
|
||||
Warning("Failed to find or create an env_debughistory.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
GetDebugHistory()->AddDebugHistoryLine( iCategory, pszLine );
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CC_DebugHistory_AddLine( const CCommand &args )
|
||||
{
|
||||
if ( args.ArgC() < 3 )
|
||||
{
|
||||
Warning("Incorrect parameters. Format: <category id> <line>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int iCategory = atoi(args[ 1 ]);
|
||||
const char *pszLine = args[ 2 ];
|
||||
AddDebugHistoryLine( iCategory, pszLine );
|
||||
}
|
||||
static ConCommand dbghist_addline( "dbghist_addline", CC_DebugHistory_AddLine, "Add a line to the debug history. Format: <category id> <line>", FCVAR_NONE );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CC_DebugHistory_Dump( const CCommand &args )
|
||||
{
|
||||
if ( args.ArgC() < 2 )
|
||||
{
|
||||
Warning("Incorrect parameters. Format: <category id>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( GetDebugHistory() )
|
||||
{
|
||||
int iCategory = atoi(args[ 1 ]);
|
||||
GetDebugHistory()->DumpDebugHistory( iCategory );
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand dbghist_dump("dbghist_dump", CC_DebugHistory_Dump,
|
||||
"Dump the debug history to the console. Format: <category id>\n"
|
||||
" Categories:\n"
|
||||
" 0: Entity I/O\n"
|
||||
" 1: AI Decisions\n"
|
||||
" 2: Scene Print\n"
|
||||
" 3: Alyx Blind\n"
|
||||
" 4: Log of damage done to player",
|
||||
FCVAR_NONE );
|
||||
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================
|
||||
#include "cbase.h"
|
||||
#include "isaverestore.h"
|
||||
#include "env_debughistory.h"
|
||||
#include "tier0/vprof.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
// Number of characters worth of debug to use per history category
|
||||
#define DEBUG_HISTORY_VERSION 6
|
||||
#define DEBUG_HISTORY_FIRST_VERSIONED 5
|
||||
#define MAX_DEBUG_HISTORY_LINE_LENGTH 256
|
||||
#define MAX_DEBUG_HISTORY_LENGTH (1000 * MAX_DEBUG_HISTORY_LINE_LENGTH)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Stores debug history in savegame files for debugging reference
|
||||
//-----------------------------------------------------------------------------
|
||||
class CDebugHistory : public CBaseEntity
|
||||
{
|
||||
DECLARE_CLASS( CDebugHistory, CBaseEntity );
|
||||
public:
|
||||
DECLARE_DATADESC();
|
||||
|
||||
void Spawn();
|
||||
void AddDebugHistoryLine( int iCategory, const char *szLine );
|
||||
void ClearHistories( void );
|
||||
void DumpDebugHistory( int iCategory );
|
||||
|
||||
int Save( ISave &save );
|
||||
int Restore( IRestore &restore );
|
||||
|
||||
private:
|
||||
char m_DebugLines[MAX_HISTORY_CATEGORIES][MAX_DEBUG_HISTORY_LENGTH];
|
||||
char *m_DebugLineEnd[MAX_HISTORY_CATEGORIES];
|
||||
};
|
||||
|
||||
BEGIN_DATADESC( CDebugHistory )
|
||||
//DEFINE_FIELD( m_DebugLines, FIELD_CHARACTER ), // Not saved because we write it out manually
|
||||
//DEFINE_FIELD( m_DebugLineEnd, FIELD_CHARACTER ),
|
||||
END_DATADESC()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( env_debughistory, CDebugHistory );
|
||||
|
||||
// The handle to the debug history singleton. Created on first access via GetDebugHistory.
|
||||
static CHandle< CDebugHistory > s_DebugHistory;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Spawn
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDebugHistory::Spawn()
|
||||
{
|
||||
BaseClass::Spawn();
|
||||
|
||||
#ifdef DISABLE_DEBUG_HISTORY
|
||||
UTIL_Remove( this );
|
||||
#else
|
||||
if ( g_pGameRules && g_pGameRules->IsMultiplayer() )
|
||||
{
|
||||
UTIL_Remove( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning( "DEBUG HISTORY IS ENABLED. Disable before release (in env_debughistory.h).\n" );
|
||||
}
|
||||
#endif
|
||||
|
||||
ClearHistories();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDebugHistory::AddDebugHistoryLine( int iCategory, const char *szLine )
|
||||
{
|
||||
if ( iCategory < 0 || iCategory >= MAX_HISTORY_CATEGORIES )
|
||||
{
|
||||
Warning("Attempted to add a debughistory line to category %d. Valid categories are %d to %d.\n", iCategory, 0, (MAX_HISTORY_CATEGORIES-1) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't do debug history before the singleton is properly set up.
|
||||
if ( !m_DebugLineEnd[iCategory] )
|
||||
return;
|
||||
|
||||
const char *pszRemaining = szLine;
|
||||
int iCharsToWrite = strlen( pszRemaining ) + 1; // Add 1 so that we copy the null terminator
|
||||
|
||||
// Clip the line if it's too long. Wasteful doing it this way, but keeps code below nice & simple.
|
||||
char szTmpBuffer[MAX_DEBUG_HISTORY_LINE_LENGTH];
|
||||
if ( iCharsToWrite > MAX_DEBUG_HISTORY_LINE_LENGTH)
|
||||
{
|
||||
memcpy( szTmpBuffer, szLine, sizeof(szTmpBuffer) );
|
||||
szTmpBuffer[MAX_DEBUG_HISTORY_LINE_LENGTH-1] = '\0';
|
||||
pszRemaining = szTmpBuffer;
|
||||
iCharsToWrite = MAX_DEBUG_HISTORY_LINE_LENGTH;
|
||||
}
|
||||
|
||||
while ( iCharsToWrite )
|
||||
{
|
||||
int iCharsLeftBeforeLoop = sizeof(m_DebugLines[iCategory]) - (m_DebugLineEnd[iCategory] - m_DebugLines[iCategory]);
|
||||
|
||||
// Write into the buffer
|
||||
int iWrote = MIN( iCharsToWrite, iCharsLeftBeforeLoop );
|
||||
memcpy( m_DebugLineEnd[iCategory], pszRemaining, iWrote );
|
||||
m_DebugLineEnd[iCategory] += iWrote;
|
||||
pszRemaining += iWrote;
|
||||
|
||||
// Did we loop?
|
||||
if ( iWrote == iCharsLeftBeforeLoop )
|
||||
{
|
||||
m_DebugLineEnd[iCategory] = m_DebugLines[iCategory];
|
||||
}
|
||||
|
||||
iCharsToWrite -= iWrote;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDebugHistory::DumpDebugHistory( int iCategory )
|
||||
{
|
||||
if ( iCategory < 0 || iCategory >= MAX_HISTORY_CATEGORIES )
|
||||
{
|
||||
Warning("Attempted to dump a history for category %d. Valid categories are %d to %d.\n", iCategory, 0, (MAX_HISTORY_CATEGORIES-1) );
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the start of the oldest whole debug line.
|
||||
const char *pszLine = m_DebugLineEnd[iCategory] + 1;
|
||||
if ( (pszLine - m_DebugLines[iCategory]) >= sizeof(m_DebugLines[iCategory]) )
|
||||
{
|
||||
pszLine = m_DebugLines[iCategory];
|
||||
}
|
||||
|
||||
// Are we at the start of a line? If there's a null terminator before us, then we're good to go.
|
||||
while ( (!( pszLine == m_DebugLines[iCategory] && *(m_DebugLines[iCategory]+sizeof(m_DebugLines[iCategory])-1) == '\0' ) &&
|
||||
!( pszLine != m_DebugLines[iCategory] && *(pszLine-1) == '\0' ))
|
||||
|| *pszLine == '\0' )
|
||||
{
|
||||
pszLine++;
|
||||
|
||||
// Have we looped?
|
||||
if ( (pszLine - m_DebugLines[iCategory]) >= sizeof(m_DebugLines[iCategory]) )
|
||||
{
|
||||
pszLine = m_DebugLines[iCategory];
|
||||
}
|
||||
|
||||
if ( pszLine == m_DebugLineEnd[iCategory] )
|
||||
{
|
||||
// We looped through the entire history, and found nothing.
|
||||
Msg( "Debug History of Category %d is EMPTY\n", iCategory );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Now print everything up till the end
|
||||
char szMsgBuffer[MAX_DEBUG_HISTORY_LINE_LENGTH];
|
||||
char *pszMsg = szMsgBuffer;
|
||||
Msg( "Starting Debug History Dump of Category %d\n", iCategory );
|
||||
while ( pszLine != m_DebugLineEnd[iCategory] )
|
||||
{
|
||||
*pszMsg = *pszLine;
|
||||
if ( *pszLine == '\0' )
|
||||
{
|
||||
if ( szMsgBuffer[0] != '\0' )
|
||||
{
|
||||
// Found a full line, so print it
|
||||
Msg( "%s", szMsgBuffer );
|
||||
}
|
||||
|
||||
// Clear the buffer
|
||||
pszMsg = szMsgBuffer;
|
||||
*pszMsg = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
pszMsg++;
|
||||
}
|
||||
|
||||
pszLine++;
|
||||
|
||||
// Have we looped?
|
||||
if ( (pszLine - m_DebugLines[iCategory]) >= sizeof(m_DebugLines[iCategory]) )
|
||||
{
|
||||
pszLine = m_DebugLines[iCategory];
|
||||
}
|
||||
}
|
||||
Msg("Ended Debug History Dump of Category %d\n", iCategory );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CDebugHistory::ClearHistories( void )
|
||||
{
|
||||
for ( int i = 0; i < MAX_HISTORY_CATEGORIES; i++ )
|
||||
{
|
||||
memset( m_DebugLines[i], 0, sizeof(m_DebugLines[i]) );
|
||||
m_DebugLineEnd[i] = m_DebugLines[i];
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CDebugHistory::Save( ISave &save )
|
||||
{
|
||||
int iVersion = DEBUG_HISTORY_VERSION;
|
||||
save.WriteInt( &iVersion );
|
||||
int iMaxCategorys = MAX_HISTORY_CATEGORIES;
|
||||
save.WriteInt( &iMaxCategorys );
|
||||
for ( int iCategory = 0; iCategory < MAX_HISTORY_CATEGORIES; iCategory++ )
|
||||
{
|
||||
int iEnd = m_DebugLineEnd[iCategory] - m_DebugLines[iCategory];
|
||||
save.WriteInt( &iEnd );
|
||||
save.WriteData( m_DebugLines[iCategory], MAX_DEBUG_HISTORY_LENGTH );
|
||||
}
|
||||
|
||||
return BaseClass::Save(save);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
int CDebugHistory::Restore( IRestore &restore )
|
||||
{
|
||||
ClearHistories();
|
||||
|
||||
int iVersion = restore.ReadInt();
|
||||
|
||||
if ( iVersion >= DEBUG_HISTORY_FIRST_VERSIONED )
|
||||
{
|
||||
int iMaxCategorys = restore.ReadInt();
|
||||
for ( int iCategory = 0; iCategory < MIN(iMaxCategorys,MAX_HISTORY_CATEGORIES); iCategory++ )
|
||||
{
|
||||
int iEnd = restore.ReadInt();
|
||||
m_DebugLineEnd[iCategory] = m_DebugLines[iCategory] + iEnd;
|
||||
restore.ReadData( m_DebugLines[iCategory], sizeof(m_DebugLines[iCategory]), 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int iMaxCategorys = iVersion;
|
||||
for ( int iCategory = 0; iCategory < MIN(iMaxCategorys,MAX_HISTORY_CATEGORIES); iCategory++ )
|
||||
{
|
||||
int iEnd = restore.ReadInt();
|
||||
m_DebugLineEnd[iCategory] = m_DebugLines[iCategory] + iEnd;
|
||||
restore.ReadData( m_DebugLines[iCategory], sizeof(m_DebugLines[iCategory]), 0 );
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::Restore(restore);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Singleton debug history. Created by first usage.
|
||||
//-----------------------------------------------------------------------------
|
||||
CDebugHistory *GetDebugHistory()
|
||||
{
|
||||
#ifdef DISABLE_DEBUG_HISTORY
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
if ( g_pGameRules && g_pGameRules->IsMultiplayer() )
|
||||
return NULL;
|
||||
|
||||
if ( s_DebugHistory == NULL )
|
||||
{
|
||||
CBaseEntity *pEnt = gEntList.FindEntityByClassname( NULL, "env_debughistory" );
|
||||
if ( pEnt )
|
||||
{
|
||||
s_DebugHistory = dynamic_cast<CDebugHistory*>(pEnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
s_DebugHistory = ( CDebugHistory * )CreateEntityByName( "env_debughistory" );
|
||||
if ( s_DebugHistory )
|
||||
{
|
||||
s_DebugHistory->Spawn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert( s_DebugHistory );
|
||||
return s_DebugHistory;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void AddDebugHistoryLine( int iCategory, const char *pszLine )
|
||||
{
|
||||
#ifdef DISABLE_DEBUG_HISTORY
|
||||
return;
|
||||
#else
|
||||
if ( g_pGameRules && g_pGameRules->IsMultiplayer() )
|
||||
return;
|
||||
|
||||
if ( !GetDebugHistory() )
|
||||
{
|
||||
Warning("Failed to find or create an env_debughistory.\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
GetDebugHistory()->AddDebugHistoryLine( iCategory, pszLine );
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CC_DebugHistory_AddLine( const CCommand &args )
|
||||
{
|
||||
if ( !UTIL_IsCommandIssuedByServerAdmin() )
|
||||
return;
|
||||
|
||||
if ( args.ArgC() < 3 )
|
||||
{
|
||||
Warning("Incorrect parameters. Format: <category id> <line>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int iCategory = atoi(args[ 1 ]);
|
||||
const char *pszLine = args[ 2 ];
|
||||
AddDebugHistoryLine( iCategory, pszLine );
|
||||
}
|
||||
static ConCommand dbghist_addline( "dbghist_addline", CC_DebugHistory_AddLine, "Add a line to the debug history. Format: <category id> <line>", FCVAR_NONE );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CC_DebugHistory_Dump( const CCommand &args )
|
||||
{
|
||||
if ( !UTIL_IsCommandIssuedByServerAdmin() )
|
||||
return;
|
||||
|
||||
if ( args.ArgC() < 2 )
|
||||
{
|
||||
Warning("Incorrect parameters. Format: <category id>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( GetDebugHistory() )
|
||||
{
|
||||
int iCategory = atoi(args[ 1 ]);
|
||||
GetDebugHistory()->DumpDebugHistory( iCategory );
|
||||
}
|
||||
}
|
||||
|
||||
static ConCommand dbghist_dump("dbghist_dump", CC_DebugHistory_Dump,
|
||||
"Dump the debug history to the console. Format: <category id>\n"
|
||||
" Categories:\n"
|
||||
" 0: Entity I/O\n"
|
||||
" 1: AI Decisions\n"
|
||||
" 2: Scene Print\n"
|
||||
" 3: Alyx Blind\n"
|
||||
" 4: Log of damage done to player",
|
||||
FCVAR_NONE );
|
||||
|
||||
|
Reference in New Issue
Block a user