diff options
Diffstat (limited to 'mp/src/game/shared/predictableid.cpp')
| -rw-r--r-- | mp/src/game/shared/predictableid.cpp | 325 |
1 files changed, 325 insertions, 0 deletions
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
|