Fix writing multiple messages on client script NetMsg

This commit is contained in:
samisalreadytaken 2022-02-18 17:00:00 +03:00
parent 4b8f386c94
commit 6d3c53fe0f
2 changed files with 185 additions and 44 deletions

View File

@ -1263,6 +1263,24 @@ CNetMsgScriptHelper *g_ScriptNetMsg = &scriptnetmsg;
#define DLL_LOC_STR "[Client]" #define DLL_LOC_STR "[Client]"
#endif #endif
#ifdef GAME_DLL
#define SCRIPT_NETMSG_WRITE_FUNC
#else
#define SCRIPT_NETMSG_WRITE_FUNC if ( m_bWriteIgnore ) { return; }
#endif
#ifdef _DEBUG
#ifdef GAME_DLL
#define DebugNetMsg( l, ... ) do { extern ConVar developer; if (developer.GetInt() >= l) ConColorMsg( Color(100, 225, 255, 255), __VA_ARGS__ ); } while (0);
#else
#define DebugNetMsg( l, ... ) do { extern ConVar developer; if (developer.GetInt() >= l) ConColorMsg( Color(100, 225, 175, 255), __VA_ARGS__ ); } while (0);
#endif
#define DebugWarning(...) Warning( __VA_ARGS__ )
#else
#define DebugNetMsg(...) (void)(0)
#define DebugWarning(...) (void)(0)
#endif
// Keep track of message names to print on failure // Keep track of message names to print on failure
#ifdef _DEBUG #ifdef _DEBUG
@ -1270,7 +1288,7 @@ struct NetMsgHook_t
{ {
void Set( const char *s ) void Set( const char *s )
{ {
hash = (int)HashStringCaseless( s ); hash = CNetMsgScriptHelper::Hash( s );
name = strdup(s); name = strdup(s);
} }
@ -1310,8 +1328,23 @@ static const char *HasNetMsgCollision( int hash, const char *ignore )
inline int CNetMsgScriptHelper::Hash( const char *key )
{
int hash = HashStringCaseless( key );
Assert( hash < (1 << SCRIPT_NETMSG_HEADER_BITS) );
return hash;
}
void CNetMsgScriptHelper::WriteToBuffer( bf_write *bf ) void CNetMsgScriptHelper::WriteToBuffer( bf_write *bf )
{ {
#ifdef CLIENT_DLL
Assert( m_nQueueCount < ( 1 << SCRIPT_NETMSG_QUEUE_BITS ) );
bf->WriteUBitLong( m_nQueueCount, SCRIPT_NETMSG_QUEUE_BITS );
DebugNetMsg( 2, DLL_LOC_STR " CNetMsgScriptHelper::WriteToBuffer() count(%d) size(%d)\n",
m_nQueueCount, m_MsgOut.GetNumBitsWritten() + SCRIPT_NETMSG_QUEUE_BITS );
#endif
bf->WriteBits( m_MsgOut.GetData(), m_MsgOut.GetNumBitsWritten() ); bf->WriteBits( m_MsgOut.GetData(), m_MsgOut.GetNumBitsWritten() );
} }
@ -1324,8 +1357,7 @@ void CNetMsgScriptHelper::Reset()
#ifdef GAME_DLL #ifdef GAME_DLL
m_filter.Reset(); m_filter.Reset();
#else #else
m_MsgIn_()Reset(); m_iLastBit = 0;
m_bWriteReady = false;
#endif #endif
} }
@ -1344,11 +1376,16 @@ void CNetMsgScriptHelper::LevelShutdownPreVM()
{ {
Reset(); Reset();
if ( m_Hooks ) if ( m_Hooks )
{
g_pScriptVM->ReleaseScript( m_Hooks ); g_pScriptVM->ReleaseScript( m_Hooks );
}
m_Hooks = NULL; m_Hooks = NULL;
#ifdef CLIENT_DLL
m_bWriteReady = m_bWriteIgnore = false;
m_MsgIn.Reset();
#else
m_MsgIn = NULL;
#endif
#ifdef _DEBUG #ifdef _DEBUG
g_NetMsgHooks.Purge(); g_NetMsgHooks.Purge();
#endif #endif
@ -1385,7 +1422,7 @@ void CNetMsgScriptHelper::ReceiveMessage( bf_read &msg )
m_MsgIn.StartReading( msg.m_pData, msg.m_nDataBytes ); m_MsgIn.StartReading( msg.m_pData, msg.m_nDataBytes );
#endif #endif
word hash = m_MsgIn_()ReadWord(); DebugNetMsg( 2, DLL_LOC_STR " " __FUNCTION__ "()\n" );
// Don't do anything if there's no VM here. This can happen if a message from the server goes to a VM-less client, or vice versa. // Don't do anything if there's no VM here. This can happen if a message from the server goes to a VM-less client, or vice versa.
if ( !g_pScriptVM ) if ( !g_pScriptVM )
@ -1394,26 +1431,42 @@ void CNetMsgScriptHelper::ReceiveMessage( bf_read &msg )
return; return;
} }
ScriptVariant_t hfn;
if ( g_pScriptVM->GetValue( m_Hooks, hash, &hfn ) )
{
#ifdef GAME_DLL #ifdef GAME_DLL
if ( g_pScriptVM->Call( hfn, NULL, true, NULL, pPlayer->m_hScriptInstance ) == SCRIPT_ERROR ) int count = m_MsgIn_()ReadUBitLong( SCRIPT_NETMSG_QUEUE_BITS );
#else DebugNetMsg( 2, " msg count %d\n", count );
if ( g_pScriptVM->ExecuteFunction( hfn, NULL, 0, NULL, NULL, true ) == SCRIPT_ERROR ) while ( count-- )
#endif #endif
{
#ifdef _DEBUG
DevWarning( 1, DLL_LOC_STR " NetMsg: invalid callback '%s'\n", GetNetMsgName( hash ) );
#else
DevWarning( 1, DLL_LOC_STR " NetMsg: invalid callback [%d]\n", hash );
#endif
}
g_pScriptVM->ReleaseValue( hfn );
}
else
{ {
DevWarning( 1, DLL_LOC_STR " NetMsg hook not found [%d]\n", hash ); int hash = m_MsgIn_()ReadWord();
#ifdef _DEBUG
const char *msgName = GetNetMsgName( hash );
DebugNetMsg( 2, " -- begin msg [%d]%s\n", hash, msgName );
#endif
ScriptVariant_t hfn;
if ( g_pScriptVM->GetValue( m_Hooks, hash, &hfn ) )
{
#ifdef GAME_DLL
if ( g_pScriptVM->Call( hfn, NULL, true, NULL, pPlayer->m_hScriptInstance ) == SCRIPT_ERROR )
#else
if ( g_pScriptVM->ExecuteFunction( hfn, NULL, 0, NULL, NULL, true ) == SCRIPT_ERROR )
#endif
{
#ifdef _DEBUG
DevWarning( 1, DLL_LOC_STR " NetMsg: invalid callback '%s'\n", GetNetMsgName( hash ) );
#else
DevWarning( 1, DLL_LOC_STR " NetMsg: invalid callback [%d]\n", hash );
#endif
}
g_pScriptVM->ReleaseValue( hfn );
}
else
{
DevWarning( 1, DLL_LOC_STR " NetMsg hook not found [%d]\n", hash );
}
DebugNetMsg( 2, " -- end msg\n" );
} }
} }
@ -1422,18 +1475,50 @@ void CNetMsgScriptHelper::ReceiveMessage( bf_read &msg )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CNetMsgScriptHelper::Start( const char *msg ) void CNetMsgScriptHelper::Start( const char *msg )
{ {
if ( !msg || !msg[0] )
{
g_pScriptVM->RaiseException( DLL_LOC_STR "NetMsg: invalid message name" );
return;
}
DebugNetMsg( 1, DLL_LOC_STR " " __FUNCTION__ "() [%d]%s\n", Hash( msg ), msg );
#ifdef CLIENT_DLL
// Client can write multiple messages in a frame before the usercmd is sent,
// this queue system ensures client messages are written to the cmd all at once.
// NOTE: All messages share the same buffer.
if ( !m_bWriteReady )
{
Reset();
m_nQueueCount = 0;
m_bWriteIgnore = false;
}
else if ( m_nQueueCount == ((1<<SCRIPT_NETMSG_QUEUE_BITS)-1) )
{
Warning( DLL_LOC_STR " NetMsg queue is full, cannot write '%s'!\n", msg );
m_bWriteIgnore = true;
return;
}
++m_nQueueCount;
#else
Reset(); Reset();
m_MsgOut.WriteWord( HashStringCaseless(msg) ); #endif
m_MsgOut.WriteWord( Hash( msg ) );
} }
#ifdef GAME_DLL
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// server -> client // server -> client
// //
// Sends an exclusive usermessage. // Sends an exclusive usermessage.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifdef GAME_DLL
void CNetMsgScriptHelper::Send( HSCRIPT player, bool bReliable ) void CNetMsgScriptHelper::Send( HSCRIPT player, bool bReliable )
{ {
DebugNetMsg( 1, DLL_LOC_STR " " __FUNCTION__ "() size(%d)\n", GetNumBitsWritten() );
CBaseEntity *pPlayer = ToEnt(player); CBaseEntity *pPlayer = ToEnt(player);
if ( pPlayer ) if ( pPlayer )
{ {
@ -1457,6 +1542,8 @@ void CNetMsgScriptHelper::Send( HSCRIPT player, bool bReliable )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CNetMsgScriptHelper::Send() void CNetMsgScriptHelper::Send()
{ {
DebugNetMsg( 1, DLL_LOC_STR " " __FUNCTION__ "() size(%d)\n", m_bWriteIgnore ? 0 : GetNumBitsWritten() );
m_bWriteReady = true; m_bWriteReady = true;
} }
#endif #endif
@ -1466,17 +1553,29 @@ void CNetMsgScriptHelper::Send()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CNetMsgScriptHelper::Receive( const char *msg, HSCRIPT func ) void CNetMsgScriptHelper::Receive( const char *msg, HSCRIPT func )
{ {
if ( !msg || !msg[0] )
{
g_pScriptVM->RaiseException( DLL_LOC_STR "NetMsg: invalid message name" );
return;
}
#ifdef _DEBUG
int hash = Hash( msg );
const char *psz = HasNetMsgCollision( hash, msg );
AssertMsg3( !psz, DLL_LOC_STR " NetMsg hash collision! [%d] '%s', '%s'\n", hash, msg, psz );
NetMsgHook_t &hook = g_NetMsgHooks[ g_NetMsgHooks.AddToTail() ];
hook.Set( msg );
#endif
if ( func ) if ( func )
{ {
#ifdef _DEBUG g_pScriptVM->SetValue( m_Hooks, Hash( msg ), func );
NetMsgHook_t &hook = g_NetMsgHooks[ g_NetMsgHooks.AddToTail() ];
hook.Set( msg );
#endif
g_pScriptVM->SetValue( m_Hooks, int( HashStringCaseless(msg) ), func );
} }
else else
{ {
g_pScriptVM->ClearValue( m_Hooks, int( HashStringCaseless(msg) ) ); g_pScriptVM->ClearValue( m_Hooks, Hash( msg ) );
} }
} }
@ -1572,86 +1671,107 @@ void CNetMsgScriptHelper::AddAllPlayers()
void CNetMsgScriptHelper::WriteInt( int iValue, int bits ) void CNetMsgScriptHelper::WriteInt( int iValue, int bits )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteSBitLong( iValue, bits ); m_MsgOut.WriteSBitLong( iValue, bits );
} }
void CNetMsgScriptHelper::WriteUInt( int iValue, int bits ) void CNetMsgScriptHelper::WriteUInt( int iValue, int bits )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteUBitLong( iValue, bits ); m_MsgOut.WriteUBitLong( iValue, bits );
} }
void CNetMsgScriptHelper::WriteByte( int iValue ) void CNetMsgScriptHelper::WriteByte( int iValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteByte( iValue ); m_MsgOut.WriteByte( iValue );
} }
void CNetMsgScriptHelper::WriteChar( int iValue ) void CNetMsgScriptHelper::WriteChar( int iValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteChar( iValue ); m_MsgOut.WriteChar( iValue );
} }
void CNetMsgScriptHelper::WriteShort( int iValue ) void CNetMsgScriptHelper::WriteShort( int iValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteShort( iValue ); m_MsgOut.WriteShort( iValue );
} }
void CNetMsgScriptHelper::WriteWord( int iValue ) void CNetMsgScriptHelper::WriteWord( int iValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteWord( iValue ); m_MsgOut.WriteWord( iValue );
} }
void CNetMsgScriptHelper::WriteLong( int iValue ) void CNetMsgScriptHelper::WriteLong( int iValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteLong( iValue ); m_MsgOut.WriteLong( iValue );
} }
void CNetMsgScriptHelper::WriteFloat( float flValue ) void CNetMsgScriptHelper::WriteFloat( float flValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteFloat( flValue ); m_MsgOut.WriteFloat( flValue );
} }
void CNetMsgScriptHelper::WriteNormal( float flValue ) void CNetMsgScriptHelper::WriteNormal( float flValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteBitNormal( flValue ); m_MsgOut.WriteBitNormal( flValue );
} }
void CNetMsgScriptHelper::WriteAngle( float flValue ) void CNetMsgScriptHelper::WriteAngle( float flValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteBitAngle( flValue, 8 ); m_MsgOut.WriteBitAngle( flValue, 8 );
} }
void CNetMsgScriptHelper::WriteCoord( float flValue ) void CNetMsgScriptHelper::WriteCoord( float flValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteBitCoord( flValue ); m_MsgOut.WriteBitCoord( flValue );
} }
void CNetMsgScriptHelper::WriteVec3Coord( const Vector& rgflValue ) void CNetMsgScriptHelper::WriteVec3Coord( const Vector& rgflValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteBitVec3Coord( rgflValue ); m_MsgOut.WriteBitVec3Coord( rgflValue );
} }
void CNetMsgScriptHelper::WriteVec3Normal( const Vector& rgflValue ) void CNetMsgScriptHelper::WriteVec3Normal( const Vector& rgflValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteBitVec3Normal( rgflValue ); m_MsgOut.WriteBitVec3Normal( rgflValue );
} }
void CNetMsgScriptHelper::WriteAngles( const QAngle& rgflValue ) void CNetMsgScriptHelper::WriteAngles( const QAngle& rgflValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteBitAngles( rgflValue ); m_MsgOut.WriteBitAngles( rgflValue );
} }
void CNetMsgScriptHelper::WriteString( const char *sz ) void CNetMsgScriptHelper::WriteString( const char *sz )
{ {
SCRIPT_NETMSG_WRITE_FUNC
// Larger strings can be written but cannot be read
Assert( V_strlen(sz) < SCRIPT_NETMSG_STRING_SIZE );
m_MsgOut.WriteString( sz ); m_MsgOut.WriteString( sz );
} }
void CNetMsgScriptHelper::WriteBool( bool bValue ) void CNetMsgScriptHelper::WriteBool( bool bValue )
{ {
SCRIPT_NETMSG_WRITE_FUNC
m_MsgOut.WriteOneBit( bValue ? 1 : 0 ); m_MsgOut.WriteOneBit( bValue ? 1 : 0 );
} }
void CNetMsgScriptHelper::WriteEntity( HSCRIPT hEnt ) void CNetMsgScriptHelper::WriteEntity( HSCRIPT hEnt )
{ {
SCRIPT_NETMSG_WRITE_FUNC
CBaseEntity *p = ToEnt(hEnt); CBaseEntity *p = ToEnt(hEnt);
int i = p ? p->entindex() : -1; int i = p ? p->entindex() : -1;
m_MsgOut.WriteSBitLong( i, MAX_EDICT_BITS ); m_MsgOut.WriteSBitLong( i, MAX_EDICT_BITS );
@ -1659,6 +1779,7 @@ void CNetMsgScriptHelper::WriteEntity( HSCRIPT hEnt )
void CNetMsgScriptHelper::WriteEHandle( HSCRIPT hEnt ) void CNetMsgScriptHelper::WriteEHandle( HSCRIPT hEnt )
{ {
SCRIPT_NETMSG_WRITE_FUNC
CBaseEntity *pEnt = ToEnt( hEnt ); CBaseEntity *pEnt = ToEnt( hEnt );
long iEncodedEHandle; long iEncodedEHandle;
if ( pEnt ) if ( pEnt )
@ -1752,7 +1873,7 @@ const QAngle& CNetMsgScriptHelper::ReadAngles()
const char* CNetMsgScriptHelper::ReadString() const char* CNetMsgScriptHelper::ReadString()
{ {
static char buf[512]; static char buf[ SCRIPT_NETMSG_STRING_SIZE ];
m_MsgIn_()ReadString( buf, sizeof(buf) ); m_MsgIn_()ReadString( buf, sizeof(buf) );
return buf; return buf;
} }
@ -1790,12 +1911,15 @@ HSCRIPT CNetMsgScriptHelper::ReadEHandle()
return ToHScript( EHANDLE( iEntry, iSerialNum ) ); return ToHScript( EHANDLE( iEntry, iSerialNum ) );
} }
int CNetMsgScriptHelper::GetNumBitsWritten() inline int CNetMsgScriptHelper::GetNumBitsWritten()
{ {
return m_MsgOut.GetNumBitsWritten(); #ifdef GAME_DLL
return m_MsgOut.GetNumBitsWritten() - SCRIPT_NETMSG_HEADER_BITS;
#else
return m_MsgOut.m_iCurBit - m_iLastBit - SCRIPT_NETMSG_HEADER_BITS;
#endif
} }
#undef m_MsgIn_
BEGIN_SCRIPTDESC_ROOT_NAMED( CNetMsgScriptHelper, "CNetMsg", SCRIPT_SINGLETON "Network messages" ) BEGIN_SCRIPTDESC_ROOT_NAMED( CNetMsgScriptHelper, "CNetMsg", SCRIPT_SINGLETON "Network messages" )
@ -1818,7 +1942,7 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CNetMsgScriptHelper, "CNetMsg", SCRIPT_SINGLETON "N
#ifdef GAME_DLL #ifdef GAME_DLL
DEFINE_SCRIPTFUNC( Send, "Send a custom network message from the server to the client (max 252 bytes)" ) DEFINE_SCRIPTFUNC( Send, "Send a custom network message from the server to the client (max 252 bytes)" )
#else #else
DEFINE_SCRIPTFUNC( Send, "Send a custom network message from the client to the server (max 2045 bytes)" ) DEFINE_SCRIPTFUNC( Send, "Send a custom network message from the client to the server (max 2044 bytes)" )
#endif #endif
DEFINE_SCRIPTFUNC( WriteInt, "variable bit signed int" ) DEFINE_SCRIPTFUNC( WriteInt, "variable bit signed int" )
@ -1835,7 +1959,7 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CNetMsgScriptHelper, "CNetMsg", SCRIPT_SINGLETON "N
DEFINE_SCRIPTFUNC( WriteVec3Coord, "" ) DEFINE_SCRIPTFUNC( WriteVec3Coord, "" )
DEFINE_SCRIPTFUNC( WriteVec3Normal, "27 bit" ) DEFINE_SCRIPTFUNC( WriteVec3Normal, "27 bit" )
DEFINE_SCRIPTFUNC( WriteAngles, "" ) DEFINE_SCRIPTFUNC( WriteAngles, "" )
DEFINE_SCRIPTFUNC( WriteString, "" ) DEFINE_SCRIPTFUNC( WriteString, "max 512 bytes at once" )
DEFINE_SCRIPTFUNC( WriteBool, "1 bit" ) DEFINE_SCRIPTFUNC( WriteBool, "1 bit" )
DEFINE_SCRIPTFUNC( WriteEntity, "11 bit (entindex)" ) DEFINE_SCRIPTFUNC( WriteEntity, "11 bit (entindex)" )
DEFINE_SCRIPTFUNC( WriteEHandle, "32 bit long" ) DEFINE_SCRIPTFUNC( WriteEHandle, "32 bit long" )
@ -1854,7 +1978,7 @@ BEGIN_SCRIPTDESC_ROOT_NAMED( CNetMsgScriptHelper, "CNetMsg", SCRIPT_SINGLETON "N
DEFINE_SCRIPTFUNC( ReadVec3Coord, "" ) DEFINE_SCRIPTFUNC( ReadVec3Coord, "" )
DEFINE_SCRIPTFUNC( ReadVec3Normal, "" ) DEFINE_SCRIPTFUNC( ReadVec3Normal, "" )
DEFINE_SCRIPTFUNC( ReadAngles, "" ) DEFINE_SCRIPTFUNC( ReadAngles, "" )
DEFINE_SCRIPTFUNC( ReadString, "max 512 bytes at once" ) DEFINE_SCRIPTFUNC( ReadString, "" )
DEFINE_SCRIPTFUNC( ReadBool, "" ) DEFINE_SCRIPTFUNC( ReadBool, "" )
DEFINE_SCRIPTFUNC( ReadEntity, "" ) DEFINE_SCRIPTFUNC( ReadEntity, "" )
DEFINE_SCRIPTFUNC( ReadEHandle, "" ) DEFINE_SCRIPTFUNC( ReadEHandle, "" )

View File

@ -17,12 +17,17 @@ void RegisterScriptSingletons();
#ifdef CLIENT_DLL #ifdef CLIENT_DLL
// usercmd // usercmd
#define SCRIPT_NETMSG_DATA_SIZE ( ( 1 << 11 ) - 1 ) #define SCRIPT_NETMSG_DATA_SIZE ( ( 1 << 11 ) - 1 )
#else #else
// usermsg // usermsg
#define SCRIPT_NETMSG_DATA_SIZE MAX_USER_MSG_DATA #define SCRIPT_NETMSG_DATA_SIZE MAX_USER_MSG_DATA
#endif #endif
#define SCRIPT_NETMSG_QUEUE_BITS 3 // determines the number of custom messages client can write to a usercmd
#define SCRIPT_NETMSG_HEADER_BITS (sizeof(word) << 3)
#define SCRIPT_NETMSG_STRING_SIZE 512
#ifdef CLIENT_DLL #ifdef CLIENT_DLL
class CNetMsgScriptHelper : public CAutoGameSystem class CNetMsgScriptHelper : public CAutoGameSystem
#else #else
@ -40,18 +45,28 @@ private:
CRecipientFilter m_filter; CRecipientFilter m_filter;
#else #else
bf_read m_MsgIn; bf_read m_MsgIn;
unsigned int m_nQueueCount;
bool m_bWriteIgnore;
#endif #endif
HSCRIPT m_Hooks; HSCRIPT m_Hooks;
bf_write m_MsgOut; bf_write m_MsgOut;
byte m_MsgData[ PAD_NUMBER( SCRIPT_NETMSG_DATA_SIZE, 4 ) ]; byte m_MsgData[ PAD_NUMBER( SCRIPT_NETMSG_DATA_SIZE, 4 ) ];
public:
#ifdef CLIENT_DLL #ifdef CLIENT_DLL
CNetMsgScriptHelper() : m_Hooks(NULL), m_bWriteReady(false) {} int m_iLastBit;
#else
CNetMsgScriptHelper() : m_Hooks(NULL) {}
#endif #endif
public:
CNetMsgScriptHelper() : m_Hooks(NULL)
#ifdef CLIENT_DLL
, m_bWriteReady(0), m_bWriteIgnore(0), m_nQueueCount(0), m_iLastBit(0)
#else
, m_MsgIn(0)
#endif
{}
public: public:
#ifdef CLIENT_DLL #ifdef CLIENT_DLL
bool Init(); // IGameSystem bool Init(); // IGameSystem
@ -135,6 +150,8 @@ public:
//int GetNumBitsLeft(); // unreliable on server because of usercmds. so just do away with it //int GetNumBitsLeft(); // unreliable on server because of usercmds. so just do away with it
int GetNumBitsWritten(); int GetNumBitsWritten();
public:
static inline int Hash( const char *key );
}; };
extern CNetMsgScriptHelper *g_ScriptNetMsg; extern CNetMsgScriptHelper *g_ScriptNetMsg;