From 39ed87570bdb2f86969d4be821c94b722dc71179 Mon Sep 17 00:00:00 2001 From: Joe Ludwig Date: Wed, 26 Jun 2013 15:22:04 -0700 Subject: First version of the SOurce SDK 2013 --- mp/src/game/shared/predictableid.cpp | 325 +++++++++++++++++++++++++++++++++++ 1 file changed, 325 insertions(+) create mode 100644 mp/src/game/shared/predictableid.cpp (limited to 'mp/src/game/shared/predictableid.cpp') diff --git a/mp/src/game/shared/predictableid.cpp b/mp/src/game/shared/predictableid.cpp new file mode 100644 index 00000000..aa6b64d7 --- /dev/null +++ b/mp/src/game/shared/predictableid.cpp @@ -0,0 +1,325 @@ +//========= Copyright 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 ) +//----------------------------------------------------------------------------- +// Purpose: Helper class for resetting instance numbers, etc. +//----------------------------------------------------------------------------- +class CPredictableIdHelper +{ +public: + CPredictableIdHelper() + { + Reset( -1 ); + } + + void Reset( int command ) + { + m_nCurrentCommand = command; + m_nCount = 0; + memset( m_Entries, 0, sizeof( m_Entries ) ); + } + + 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 -- cgit v1.2.3