|
|
//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "checksum_crc.h"
#include "tier1/strtools.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#if !defined( NO_ENTITY_PREDICTION ) && defined( USE_PREDICTABLEID )
//-----------------------------------------------------------------------------
// Purpose: Helper class for resetting instance numbers, etc.
//-----------------------------------------------------------------------------
class CPredictableIdHelper { public: CPredictableIdHelper() { memset( m_Entries, 0, sizeof( m_Entries ) ); Reset( -1 ); }
void Reset( int command ) { m_nCurrentCommand = command; m_nCount = 0; }
int AddEntry( int command, int hash ) { // Clear list if command number changes
if ( command != m_nCurrentCommand ) { Reset( command ); }
entry *e = FindOrAddEntry( hash ); if ( !e ) return 0; e->count++; return e->count-1; }
private:
enum { MAX_ENTRIES = 256, };
struct entry { int hash; int count; };
entry *FindOrAddEntry( int hash ) { int i; for ( i = 0; i < m_nCount; i++ ) { entry *e = &m_Entries[ i ]; if ( e->hash == hash ) return e; }
if ( m_nCount >= MAX_ENTRIES ) { // assert( 0 );
return NULL; }
entry *e = &m_Entries[ m_nCount++ ]; e->hash = hash; e->count = 0; return e; }
int m_nCurrentCommand; int m_nCount; entry m_Entries[ MAX_ENTRIES ]; };
static CPredictableIdHelper g_Helper;
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CPredictableId::CPredictableId( void ) { memset( &m_PredictableID, 0, sizeof( m_PredictableID ) ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CPredictableId::ResetInstanceCounters( void ) { g_Helper.Reset( -1 ); }
//-----------------------------------------------------------------------------
// Purpose: Is the Id being used
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CPredictableId::IsActive( void ) const { if ( *(const int *)&m_PredictableID == 0 ) return false;
return true; }
//-----------------------------------------------------------------------------
// Purpose:
// Input : playerIndex -
//-----------------------------------------------------------------------------
void CPredictableId::SetPlayer( int playerIndex ) { m_PredictableID.player = (unsigned int)playerIndex; }
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
int CPredictableId::GetPlayer( void ) const { return (int)m_PredictableID.player; }
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
int CPredictableId::GetCommandNumber( void ) const { return (int)m_PredictableID.command; }
//-----------------------------------------------------------------------------
// Purpose:
// Input : commandNumber -
//-----------------------------------------------------------------------------
void CPredictableId::SetCommandNumber( int commandNumber ) { m_PredictableID.command = (unsigned int)commandNumber; }
/*
bool CPredictableId::IsCommandNumberEqual( int testNumber ) const { if ( ( testNumber & ((1<<10) - 1) ) == m_PredictableID.command ) return true;
return false; } */
//-----------------------------------------------------------------------------
// Purpose:
// Input : *classname -
// *module -
// line -
// Output : static int
//-----------------------------------------------------------------------------
static int ClassFileLineHash( const char *classname, const char *module, int line ) { CRC32_t retval;
CRC32_Init( &retval );
char tempbuffer[ 512 ]; // ACK, have to go lower case due to issues with .dsp having different cases of drive
// letters, etc.!!!
Q_strncpy( tempbuffer, classname, sizeof( tempbuffer ) ); Q_strlower( tempbuffer ); CRC32_ProcessBuffer( &retval, (void *)tempbuffer, Q_strlen( tempbuffer ) ); Q_strncpy( tempbuffer, module, sizeof( tempbuffer ) ); Q_strlower( tempbuffer ); CRC32_ProcessBuffer( &retval, (void *)tempbuffer, Q_strlen( tempbuffer ) ); CRC32_ProcessBuffer( &retval, (void *)&line, sizeof( int ) );
CRC32_Final( &retval );
return (int)retval; }
//-----------------------------------------------------------------------------
// Purpose: Create a predictable id of the specified parameter set
// Input : player -
// command -
// *classname -
// *module -
// line -
//-----------------------------------------------------------------------------
void CPredictableId::Init( int player, int command, const char *classname, const char *module, int line ) { SetPlayer( player ); SetCommandNumber( command );
m_PredictableID.hash = ClassFileLineHash( classname, module, line );
// Use helper to determine instance number this command
int instance = g_Helper.AddEntry( command, m_PredictableID.hash );
// Set appropriate instance number
SetInstanceNumber( instance ); }
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
int CPredictableId::GetHash( void ) const { return (int)m_PredictableID.hash; }
//-----------------------------------------------------------------------------
// Purpose:
// Input : counter -
//-----------------------------------------------------------------------------
void CPredictableId::SetInstanceNumber( int counter ) { m_PredictableID.instance = (unsigned int)counter; }
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
int CPredictableId::GetInstanceNumber( void ) const { return (int)m_PredictableID.instance; }
// Client only
//-----------------------------------------------------------------------------
// Purpose:
// Input : ack -
//-----------------------------------------------------------------------------
void CPredictableId::SetAcknowledged( bool ack ) { m_PredictableID.ack = ack ? 1 : 0; }
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CPredictableId::GetAcknowledged( void ) const { return m_PredictableID.ack ? true : false; }
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
int CPredictableId::GetRaw( void ) const { return *(int *)&m_PredictableID; }
//-----------------------------------------------------------------------------
// Purpose:
// Input : raw -
//-----------------------------------------------------------------------------
void CPredictableId::SetRaw( int raw ) { *(int *)&m_PredictableID = raw; }
//-----------------------------------------------------------------------------
// Purpose: Determine if one id is == another, ignores Acknowledged state
// Input : other -
// Output : bool CPredictableId::operator
//-----------------------------------------------------------------------------
bool CPredictableId::operator ==( const CPredictableId& other ) const { if ( this == &other ) return true;
if ( GetPlayer() != other.GetPlayer() ) return false; if ( GetCommandNumber() != other.GetCommandNumber() ) return false; if ( GetHash() != other.GetHash() ) return false; if ( GetInstanceNumber() != other.GetInstanceNumber() ) return false; return true; }
bool CPredictableId::operator !=( const CPredictableId& other ) const { return !(*this == other); }
//-----------------------------------------------------------------------------
// Purpose:
// Output : char const
//-----------------------------------------------------------------------------
const char *CPredictableId::Describe( void ) const { static char desc[ 128 ];
Q_snprintf( desc, sizeof( desc ), "pl(%i) cmd(%i) hash(%i) inst(%i) ack(%s)", GetPlayer(), GetCommandNumber(), GetHash(), GetInstanceNumber() , GetAcknowledged() ? "true" : "false" );
return desc; } #endif
|