csgo-2018-source/game/server/global_event_log.cpp
2021-07-24 21:11:47 -07:00

375 lines
7.5 KiB
C++

//============ Copyright (c) Valve Corporation, All rights reserved. ============
//
// work in progress
//
//===============================================================================
#include "cbase.h"
#include "global_event_log.h"
#include "filesystem.h"
#include "utlbuffer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#ifdef _PS3
#define _vscprintf vprintf
#define vsprintf_s vsnprintf
#endif
CGlobalEventLog GlobalEventLog;
static CUtlSymbolTable EventSymbols;
static ConVar global_event_log_enabled( "global_event_log_enabled", "0", FCVAR_CHEAT, "Enables the global event log system" );
class CGlobalEventLine
{
public:
CGlobalEventLine( );
~CGlobalEventLine( );
void Clear( );
bool SetStaticText( const char *pszValue );
bool SetVaryingText( const char *pszValue );
bool IsDirty( ) { return m_bDirty; }
void Write( CUtlBuffer *pBuffer );
void ClearDirty( );
private:
CUtlSymbol m_ValueSymbol;
char *m_pszValue;
bool m_bDirty;
};
CGlobalEventLine::CGlobalEventLine( )
{
m_ValueSymbol = UTL_INVAL_SYMBOL;
m_pszValue = NULL;
m_bDirty = true;
}
CGlobalEventLine::~CGlobalEventLine( )
{
Clear();
}
void CGlobalEventLine::Clear( )
{
m_ValueSymbol = UTL_INVAL_SYMBOL;
if ( m_pszValue != NULL )
{
delete m_pszValue;
m_pszValue = NULL;
}
m_bDirty = true;
}
bool CGlobalEventLine::SetStaticText( const char *pszValue )
{
if ( m_ValueSymbol != UTL_INVAL_SYMBOL && m_ValueSymbol == EventSymbols.Find( pszValue ) )
{
return false;
}
Clear();
m_ValueSymbol = EventSymbols.AddString( pszValue );
return true;
}
bool CGlobalEventLine::SetVaryingText( const char *pszValue )
{
if ( m_pszValue && strcmpi( m_pszValue, pszValue ) == 0 )
{ // no change
return false;
}
Clear();
m_pszValue = ( char * )malloc( strlen( pszValue ) + 1 );
strcpy( m_pszValue, pszValue );
return true;
}
void CGlobalEventLine::Write( CUtlBuffer *pBuffer )
{
const char *pszValue;
if ( m_pszValue != NULL )
{
pszValue = m_pszValue;
}
else
{
pszValue = EventSymbols.String( m_ValueSymbol );
}
if ( strchr( pszValue, ' ' ) != NULL )
{
pBuffer->Printf( "\"%s\"\n", pszValue );
}
else
{
pBuffer->Printf( "%s\n", pszValue );
}
}
void CGlobalEventLine::ClearDirty( )
{
m_bDirty = false;
}
class CGlobalEvent
{
public:
CGlobalEvent( const char *pszName, unsigned int nID, bool bIsHighLevel, CGlobalEvent *pParent = NULL );
bool AddValue( bool bVarying, const char *pszKey, const char *pszValue );
unsigned int GetID( ) { return m_nID; }
bool IsDirty( ) { return m_bDirty; }
void Write( CUtlBuffer *pBuffer );
void ClearDirty( );
private:
unsigned int m_nID;
CUtlSymbol m_Name;
float m_flTime;
bool m_bIsHighLevel;
bool m_bFullUpdate;
bool m_bDirty;
CGlobalEvent *m_pParent;
CUtlMap< CUtlSymbol, CGlobalEventLine * > m_EventLines;
};
CGlobalEvent::CGlobalEvent( const char *pszName, unsigned int nID, bool bIsHighLevel, CGlobalEvent *pParent ) :
m_EventLines( DefLessFunc( const CUtlSymbol ) )
{
m_Name = EventSymbols.AddString( pszName );
m_nID = nID;
m_bIsHighLevel = bIsHighLevel;
m_pParent = pParent;
m_bFullUpdate = true;
m_flTime = gpGlobals->curtime;
}
bool CGlobalEvent::AddValue( bool bVarying, const char *pszKey, const char *pszValue )
{
CUtlSymbol KeyID;
CGlobalEventLine *pEvent;
int nIndex;
bool bResult;
KeyID = EventSymbols.AddString( pszKey );
nIndex = m_EventLines.Find( KeyID );
if ( nIndex == m_EventLines.InvalidIndex() )
{
pEvent = new CGlobalEventLine();
m_EventLines.Insert( KeyID, pEvent );
}
else
{
pEvent = m_EventLines.Element( nIndex );
}
if ( bVarying )
{
bResult = pEvent->SetVaryingText( pszValue );
}
else
{
bResult = pEvent->SetStaticText( pszValue );
}
if ( bResult == true )
{
m_bDirty = true;
m_flTime = gpGlobals->curtime;
}
return bResult;
}
void CGlobalEvent::Write( CUtlBuffer *pBuffer )
{
pBuffer->Printf( "event %u\n", m_nID );
pBuffer->Printf( "{\n" );
if ( m_bFullUpdate )
{
const char *pszName = EventSymbols.String( m_Name );
if ( strchr( pszName, ' ' ) != NULL )
{
pBuffer->Printf( "\tName\t\"%s\"\n", pszName );
}
else
{
pBuffer->Printf( "\tName\t%s\n", pszName );
}
if ( m_pParent != NULL )
{
pBuffer->Printf( "\tParent_ID\t%u\n", m_pParent->GetID() );
}
if ( m_bIsHighLevel == true )
{
pBuffer->Printf( "\tHighLevel\t1\n" );
}
}
pBuffer->Printf( "\tTime\t%g\n", m_flTime );
for( unsigned i = 0; i < m_EventLines.Count(); i++ )
{
if ( m_EventLines.Element( i )->IsDirty() )
{
const char *pszKey = EventSymbols.String( m_EventLines.Key( i ) );
if ( strchr( pszKey, ' ' ) != NULL )
{
pBuffer->Printf( "\t\"%s\"\t", pszKey );
}
else
{
pBuffer->Printf( "\t%s\t", pszKey );
}
m_EventLines.Element( i )->Write( pBuffer );
}
}
pBuffer->Printf( "}\n" );
}
void CGlobalEvent::ClearDirty( )
{
m_bFullUpdate = false;
m_bDirty = false;
for( unsigned i = 0; i < m_EventLines.Count(); i++ )
{
m_EventLines.Element( i )->ClearDirty();
}
}
CGlobalEventLog::CGlobalEventLog( )
{
m_nNextID = 1;
}
CGlobalEvent *CGlobalEventLog::GetGlobalEvent( EGlobalEvent GlobalEvent )
{
return m_pGlobalEvents[ GlobalEvent ];
}
CGlobalEvent *CGlobalEventLog::CreateEvent( const char *pszName, bool bIsHighLevel, CGlobalEvent *pParent )
{
CGlobalEvent *pEvent = new CGlobalEvent( pszName, m_nNextID, bIsHighLevel, pParent );
m_Events.AddToTail( pEvent );
m_DirtyEvents.AddToTail( pEvent );
m_nNextID++;
return pEvent;
}
CGlobalEvent *CGlobalEventLog::CreateTempEvent( const char *pszName, CGlobalEvent *pParent )
{
CGlobalEvent *pEvent = new CGlobalEvent( pszName, m_nNextID, false, pParent );
m_TempEvents.AddToTail( pEvent );
m_DirtyEvents.AddToTail( pEvent );
m_nNextID++;
return pEvent;
}
void CGlobalEventLog::RemoveEvent( CGlobalEvent *pEvent )
{
if ( m_Events.FindAndRemove( pEvent ) == true && m_TempEvents.Find( pEvent ) == -1 )
{
m_TempEvents.AddToTail( pEvent );
}
}
void CGlobalEventLog::AddKeyValue( CGlobalEvent *pEvent, bool bVarying, const char *pszKey, const char *pszValueFormat, ... )
{
va_list Args;
int nLen;
char *pszBuffer;
CUtlSymbol KeyID;
bool bResult;
va_start( Args, pszValueFormat );
#if defined(_WIN32) || defined(_PS3)
nLen = _vscprintf( pszValueFormat, Args ) + 1;
#else
nLen = vsnprintf( NULL, 0, pszValueFormat, Args ) + 1;
#endif
pszBuffer = ( char * )stackalloc( nLen * sizeof( char ) );
V_vsnprintf( pszBuffer, nLen, pszValueFormat, Args );
bResult = pEvent->AddValue( bVarying, pszKey, pszBuffer );
if ( bResult == true && m_DirtyEvents.Find( pEvent ) == -1 )
{
m_DirtyEvents.AddToTail( pEvent );
}
}
void CGlobalEventLog::SendUpdate( )
{
if ( m_DirtyEvents.Count() == 0 )
{
return;
}
if ( global_event_log_enabled.GetBool() == true )
{
FileHandle_t fh = g_pFullFileSystem->Open( "c:\\o.events", "a" );
CUtlBuffer *pBuffer = new CUtlBuffer( 0, 0, CUtlBuffer::TEXT_BUFFER );
pBuffer->Clear();
for( int i = 0; i < m_DirtyEvents.Count(); i++ )
{
m_DirtyEvents[ i ]->Write( pBuffer );
g_pFullFileSystem->Write( pBuffer->Base(), pBuffer->TellPut(), fh );
pBuffer->Clear();
}
g_pFullFileSystem->Close( fh );
}
for( int i = 0; i < m_DirtyEvents.Count(); i++ )
{
m_DirtyEvents[ i ]->ClearDirty();
}
m_DirtyEvents.Purge();
for( int i = 0; i < m_TempEvents.Count(); i++ )
{
delete m_TempEvents[ i ];
}
m_TempEvents.Purge();
}
void CGlobalEventLog::PostInit( )
{
m_pGlobalEvents[ GLOBAL_EVENT_NPCS ] = CreateEvent( "NPCs", true );
}
void CGlobalEventLog::FrameUpdatePostEntityThink( )
{
SendUpdate();
}