//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #ifndef SHAREDVAR_H #define SHAREDVAR_H #ifdef _WIN32 #pragma once #endif #include "convar.h" #include "ispsharedmemory.h" #include "basehandle.h" #include "isaverestore.h" #pragma warning( disable : 4284 ) // warning C4284: return type for 'CNetworkVarT::operator ->' is 'int *' (ie; not a UDT or reference to a UDT. Will produce errors if applied using infix notation) #if defined( GAME_DLL ) static int Server_EHandleToInt( const EHANDLE &hIn ) { if ( hIn.Get() ) { int iSerialNum = hIn.GetSerialNumber() & (1 << NUM_NETWORKED_EHANDLE_SERIAL_NUMBER_BITS) - 1; return ( hIn.GetEntryIndex() | (iSerialNum << MAX_EDICT_BITS) ); } else { return INVALID_NETWORKED_EHANDLE_VALUE; } } #endif #if defined( CLIENT_DLL ) static EHANDLE Client_IntToEHandle( int iIn ) { if ( iIn == INVALID_NETWORKED_EHANDLE_VALUE ) { return INVALID_EHANDLE_INDEX; } else { int iEntity = iIn & ((1 << MAX_EDICT_BITS) - 1); int iSerialNum = iIn >> MAX_EDICT_BITS; EHANDLE hOut; hOut.Init( iEntity, iSerialNum ); return hOut; } } #endif class CSharedVarSaveDataOps; // Templated save/restore functions for shared vars (add specializations as needed) template< class Type > static void SharedVar_Save( ISave *pSave, Type *pValue, int iCount = 1 ) { int iNumBytes = sizeof( Type ) * iCount; pSave->WriteInt( &iNumBytes ); pSave->WriteData( (char*)( (void*)(pValue) ), iNumBytes ); } template< class Type > static void SharedVar_Restore( IRestore *pRestore, Type *pValue ) { int iNumBytes = pRestore->ReadInt(); pRestore->ReadData( (char*)( (void*)(pValue) ), iNumBytes, 0 ); } template< class Type > static bool SharedVar_IsEmpty( Type *pValue, int iCount = 1 ) { char *pChar = (char*)( (void*)(pValue) ); int iNumBytes = sizeof( Type ) * iCount; for ( int i = 0; i < iNumBytes; ++i ) { if ( pChar[i] != NULL ) { return false; } } return true; } template< class Type > static void SharedVar_MakeEmpty( Type *pValue, int iCount = 1 ) { memset( pValue, 0, sizeof( Type ) * iCount ); } // EHANDLE Save/Restore specializations template<> TEMPLATE_STATIC void SharedVar_Save( ISave *pSave, EHANDLE *pValue, int iCount ) { pSave->WriteInt( &iCount ); pSave->WriteEHandle( pValue, iCount ); } template<> TEMPLATE_STATIC void SharedVar_Restore( IRestore *pRestore, EHANDLE *pValue ) { int iCount = pRestore->ReadInt(); pRestore->ReadEHandle( pValue, iCount ); } // UtlVector Save/Restore specializations template< class Type > void SharedVar_SaveUtlVector( ISave *pSave, CUtlVector *pValue, int iCount = 1 ) { Assert( iCount == 1 ); int iNumBytes = sizeof( Type ) * pValue->Count(); pSave->WriteInt( &iNumBytes ); pSave->WriteData( (char*)( (void*)(pValue->Base()) ), iNumBytes ); } template< class Type > void SharedVar_RestoreUtlVector( IRestore *pRestore, CUtlVector *pValue ) { int iNumBytes = pRestore->ReadInt(); pValue->SetCount( iNumBytes / sizeof( Type ) ); pRestore->ReadData( (char*)( (void*)(pValue->Base()) ), iNumBytes, 0 ); } template< class Type > static bool SharedVar_IsEmptyUtlVector( CUtlVector *pValue, int iCount = 1 ) { Assert( iCount == 1 ); return ( pValue->Count() == 0 ); } template< class Type > static void SharedVar_MakeEmptyUtlVector( CUtlVector *pValue, int iCount = 1 ) { Assert( iCount == 1 ); pValue->SetCount( 0 ); } abstract_class ISharedVarBase { private: virtual void _Save( ISave *pSave ) = 0; virtual void _Restore( IRestore *pRestore ) = 0; virtual bool _IsEmpty( void ) = 0; virtual void _MakeEmpty( void ) = 0; public: friend class CSharedVarSaveDataOps; }; template< class Type, class Changer > class CSharedVarBase : public ISharedVarBase { public: CSharedVarBase( void ) { m_pSharedMemory = NULL; m_pValue = NULL; } ~CSharedVarBase( void ) { m_pSharedMemory->Release(); m_pSharedMemory = NULL; m_pValue = NULL; } void Initialize( char *pchName, int iEntNum ) { Assert( !m_pSharedMemory && !m_pValue ); m_pSharedMemory = engine->GetSinglePlayerSharedMemorySpace( pchName, iEntNum ); m_pSharedMemory->Init( sizeof( Type ) ); m_pValue = (Type*)m_pSharedMemory->Base(); } #if defined( GAME_DLL ) // Data can only be set on the server template< class C > const Type& operator=( const C &val ) { return Set( static_cast( val ) ); } template< class C > const Type& operator=( const CNetworkVarBase< C, Changer > &val ) { return Set( static_cast( *val.m_pValue ) ); } const Type& Set( const Type &val ) { *m_pValue = val; return *m_pValue; } template< class C > const Type& operator+=( const C &val ) { return Set( *m_pValue + static_cast( val ) ); } template< class C > const Type& operator-=( const C &val ) { return Set( *m_pValue - static_cast( val ) ); } template< class C > const Type& operator/=( const C &val ) { return Set( *m_pValue / static_cast( val ) ); } template< class C > const Type& operator*=( const C &val ) { return Set( *m_pValue * static_cast( val ) ); } template< class C > const Type& operator^=( const C &val ) { return Set( *m_pValue ^ static_cast( val ) ); } template< class C > const Type& operator|=( const C &val ) { return Set( *m_pValue | static_cast( val ) ); } const Type& operator++() { return (*this += 1); } Type operator--() { return (*this -= 1); } Type operator++( int ) // postfix version.. { Type val = *m_pValue; (*this += 1); return val; } Type operator--( int ) // postfix version.. { Type val = *m_pValue; (*this -= 1); return val; } // For some reason the compiler only generates type conversion warnings for this operator when used like // CNetworkVarBase = 0x1 // (it warns about converting from an int to an unsigned char). template< class C > const Type& operator&=( const C &val ) { return Set( *m_pValue & static_cast( val ) ); } operator Type&() { return *m_pValue; } Type& GetForModify() { return *m_pValue; } Type* operator->() { return m_pValue; } #endif operator const Type&() const { return *m_pValue; } const Type& Get() const { return *m_pValue; } const Type* operator->() const { return m_pValue; } private: virtual void _Save( ISave *pSave ) { SharedVar_Save( pSave, m_pValue ); } virtual void _Restore( IRestore *pRestore ) { SharedVar_Restore( pRestore, m_pValue ); } virtual bool _IsEmpty( void ) { return SharedVar_IsEmpty( m_pValue ); } virtual void _MakeEmpty( void ) { SharedVar_MakeEmpty( m_pValue ); } public: ISPSharedMemory *m_pSharedMemory; Type *m_pValue; }; // Shared color wrapper. template< class Type, class Changer > class CSharedColor32Base : public CSharedVarBase< Type, Changer > { public: #if defined( GAME_DLL ) // Data can only be set on the server inline void Init( byte rVal, byte gVal, byte bVal ) { SetR( rVal ); SetG( gVal ); SetB( bVal ); } inline void Init( byte rVal, byte gVal, byte bVal, byte aVal ) { SetR( rVal ); SetG( gVal ); SetB( bVal ); SetA( aVal ); } const Type& operator=( const Type &val ) { return Set( val ); } const Type& operator=( const CSharedColor32Base &val ) { return CSharedVarBase::Set( *val.m_pValue ); } inline void SetR( byte val ) { SetVal( CSharedColor32Base::m_pValue->r, val ); } inline void SetG( byte val ) { SetVal( CSharedColor32Base::m_pValue->g, val ); } inline void SetB( byte val ) { SetVal( CSharedColor32Base::m_pValue->b, val ); } inline void SetA( byte val ) { SetVal( CSharedColor32Base::m_pValue->a, val ); } #endif inline byte GetR() const { return CSharedColor32Base::m_pValue->r; } inline byte GetG() const { return CSharedColor32Base::m_pValue->g; } inline byte GetB() const { return CSharedColor32Base::m_pValue->b; } inline byte GetA() const { return CSharedColor32Base::m_pValue->a; } #if defined( GAME_DLL ) // Data can only be set on the server private: inline void SetVal( byte &out, const byte &in ) { out = in; } #endif }; // Shared vector wrapper. template< class Type, class Changer > class CSharedVectorBase : public CSharedVarBase< Type, Changer > { public: #if defined( GAME_DLL ) // Data can only be set on the server inline void Init( float ix=0, float iy=0, float iz=0 ) { SetX( ix ); SetY( iy ); SetZ( iz ); } const Type& operator=( const Type &val ) { return CSharedVarBase< Type, Changer >::Set( val ); } const Type& operator=( const CSharedVectorBase &val ) { return CSharedVarBase::Set( *val.m_pValue ); } inline void SetX( float val ) { SetVal( CSharedVectorBase::m_pValue->x, val ); } inline void SetY( float val ) { SetVal( CSharedVectorBase::m_pValue->y, val ); } inline void SetZ( float val ) { SetVal( CSharedVectorBase::m_pValue->z, val ); } inline void Set( int i, float val ) { SetVal( (*CSharedVectorBase::m_pValue)[i], val ); } inline float& operator[]( int i ) { return (*CSharedVectorBase::m_pValue)[i]; } const Type& operator*=( float val ) { return CSharedVarBase< Type, Changer >::Set( (*CSharedVectorBase::m_pValue) * val ); } #endif inline float GetX() const { return CSharedVectorBase::m_pValue->x; } inline float GetY() const { return CSharedVectorBase::m_pValue->y; } inline float GetZ() const { return CSharedVectorBase::m_pValue->z; } inline const float& operator[]( int i ) const { return (*CSharedVectorBase::m_pValue)[i]; } bool operator==( const Type &val ) const { return (*CSharedVectorBase::m_pValue) == (Type)val; } bool operator!=( const Type &val ) const { return (*CSharedVectorBase::m_pValue) != (Type)val; } const Type operator+( const Type &val ) const { return (*CSharedVectorBase::m_pValue) + val; } const Type operator-( const Type &val ) const { return (*CSharedVectorBase::m_pValue) - val; } const Type operator*( const Type &val ) const { return (*CSharedVectorBase::m_pValue) * val; } const Type operator*( float val ) const { return (*CSharedVectorBase::m_pValue) * val; } const Type operator/( const Type &val ) const { return (*CSharedVectorBase::m_pValue) / val; } #if defined( GAME_DLL ) // Data can only be set on the server private: inline void SetVal( float &out, float in ) { out = in; } #endif }; // Shared quaternion wrapper. template< class Type, class Changer > class CSharedQuaternionBase : public CSharedVarBase< Type, Changer > { public: #if defined( GAME_DLL ) // Data can only be set on the server inline void Init( float ix=0, float iy=0, float iz=0, float iw = 0 ) { SetX( ix ); SetY( iy ); SetZ( iz ); SetZ( iw ); } const Type& operator=( const Type &val ) { return CSharedVarBase< Type, Changer >::Set( val ); } const Type& operator=( const CSharedQuaternionBase &val ) { return CSharedVarBase::Set( *val.m_pValue ); } const Type& operator*=( float val ) { return CSharedVarBase< Type, Changer >::Set( (*CSharedQuaternionBase::m_pValue) * val ); } inline void SetX( float val ) { SetVar( CSharedQuaternionBase::m_pValue->x, val ); } inline void SetY( float val ) { SetVar( CSharedQuaternionBase::m_pValue->y, val ); } inline void SetZ( float val ) { SetVar( CSharedQuaternionBase::m_pValue->z, val ); } inline void SetW( float val ) { SetVar( CSharedQuaternionBase::m_pValue->w, val ); } inline void Set( int i, float val ) { SetVar( (*CSharedQuaternionBase::m_pValue)[i], val ); } inline float& operator[]( int i ) { return (*CSharedQuaternionBase::m_pValue)[i]; } #endif inline float GetX() const { return CSharedQuaternionBase::m_pValue->x; } inline float GetY() const { return CSharedQuaternionBase::m_pValue->y; } inline float GetZ() const { return CSharedQuaternionBase::m_pValue->z; } inline float GetW() const { return CSharedQuaternionBase::m_pValue->w; } inline const float& operator[]( int i ) const { return (*CSharedQuaternionBase::m_pValue)[i]; } bool operator==( const Type &val ) const { return (*CSharedQuaternionBase::m_pValue) == (Type)val; } bool operator!=( const Type &val ) const { return (*CSharedQuaternionBase::m_pValue) != (Type)val; } const Type operator+( const Type &val ) const { return (*CSharedQuaternionBase::m_pValue) + val; } const Type operator-( const Type &val ) const { return (*CSharedQuaternionBase::m_pValue) - val; } const Type operator*( const Type &val ) const { return (*CSharedQuaternionBase::m_pValue) * val; } const Type operator*( float val ) const { return (*CSharedQuaternionBase::m_pValue) * val; } const Type operator/( const Type &val ) const { return (*CSharedQuaternionBase::m_pValue) / val; } #if defined( GAME_DLL ) // Data can only be set on the server private: inline void SetVar( float &out, float in ) { out = in; } #endif }; // Prevent Shared Vars from using handle templates without the handle wrapper template< class Type, class Changer > class CSharedVarBase< CHandle, Changer > : public ISharedVarBase { public: CSharedVarBase( void ) { m_pSharedMemory = NULL; m_pValue = NULL; } ~CSharedVarBase( void ) { m_pSharedMemory->Release(); m_pSharedMemory = NULL; m_pValue = NULL; } protected: virtual void Shared_Handle_Vars_Must_Use_CSharedHandle_Or_CSharedHandleArray() = 0; public: ISPSharedMemory *m_pSharedMemory; CHandle *m_pValue; }; // Prevent Shared Vars from using handle templates without the handle wrapper template< class Changer > class CSharedVarBase< CBaseHandle, Changer > : public ISharedVarBase { public: CSharedVarBase( void ) { m_pSharedMemory = NULL; m_pValue = NULL; } ~CSharedVarBase( void ) { m_pSharedMemory->Release(); m_pSharedMemory = NULL; m_pValue = NULL; } protected: virtual void Shared_Handle_Vars_Must_Use_CSharedHandle_Or_CSharedHandleArray() = 0; public: ISPSharedMemory *m_pSharedMemory; CBaseHandle *m_pValue; }; // Shared handle wrapper. template< class Type, class Changer > class CSharedHandleBase : public CSharedVarBase< EHANDLE, Changer > { public: virtual void Shared_Handle_Vars_Must_Use_CSharedHandle_Or_CSharedHandleArray() {} void Initialize( char *pchName, int iEntNum ) { Assert( !this->m_pSharedMemory && !this->m_pValue ); this->m_pSharedMemory = engine->GetSinglePlayerSharedMemorySpace( pchName, iEntNum ); this->m_pSharedMemory->Init( sizeof( EHANDLE ) + sizeof( int ) ); // Also allocate memory for the int that converts to a Client handle this->m_pValue = (EHANDLE*)this->m_pSharedMemory->Base(); m_piClientIndex = (int*)((void*)(this->m_pValue + 1)); } bool operator !() const { return !GetHandle_Internal()->Get(); } #if defined( GAME_DLL ) // Data can only be set on the server const Type* operator=( const Type *val ) { return Set( val ); } const Type& operator=( const CSharedHandleBase &val ) { const EHANDLE &handle = CSharedVarBase::Set( *val.m_pValue ); return *(const Type*)handle.Get(); } const Type* Set( const Type *val ) { (*CSharedHandleBase::m_pValue) = val; // Store the int that we'll need to translate to the EHandle on the client *m_piClientIndex = Server_EHandleToInt( *CSharedHandleBase::m_pValue ); return val; } #endif operator const Type*() const { return Get_Internal(); } const Type* Get() const { return Get_Internal(); } const Type* operator->() const { return Get_Internal(); } bool operator==( const Type *val ) const { return Get_Internal() == val; } bool operator!=( const Type *val ) const { return Get_Internal() != val; } private: EHANDLE GetHandle_Internal() const { #if defined( GAME_DLL ) // Server can get the handle directly return (*CSharedHandleBase::m_pValue); #else // Client needs to get the handle translated from the stroed int EHANDLE hClient = Client_IntToEHandle( *m_piClientIndex ); return hClient; #endif } Type* Get_Internal() const { return static_cast< Type* >( GetHandle_Internal().Get() ); } void UpdateClientIndex( void ) { *m_piClientIndex = Server_EHandleToInt( *(CSharedHandleBase::m_pValue) ); } virtual void _Save( ISave *pSave ) { SharedVar_Save( pSave, this->m_pValue ); } virtual void _Restore( IRestore *pRestore ) { SharedVar_Restore( pRestore, this->m_pValue ); UpdateClientIndex(); } virtual bool _IsEmpty( void ) { return SharedVar_IsEmpty( this->m_pValue ); } virtual void _MakeEmpty( void ) { SharedVar_MakeEmpty( this->m_pValue ); } public: int *m_piClientIndex; // Pointer to ints for Client handle translations }; // Shared array wrapper. template< class Type, class Changer > class CSharedArrayBase : public CSharedVarBase< Type, Changer > { public: CSharedArrayBase( void ) { m_iCount = 0; } void Initialize( char *pchName, int iEntNum, int iCount ) { Assert( !this->m_pSharedMemory && !(CSharedArrayBase::m_pValue) && iCount > 0 ); m_iCount = iCount; this->m_pSharedMemory = engine->GetSinglePlayerSharedMemorySpace( pchName, iEntNum ); this->m_pSharedMemory->Init( sizeof( Type ) * m_iCount ); CSharedArrayBase::m_pValue = (Type*)this->m_pSharedMemory->Base(); } const int& Count() const { return m_iCount; } const Type* Get() const { return CSharedArrayBase::m_pValue; } const Type& Get( int i ) const { Assert( i >= 0 && i < m_iCount ); return CSharedArrayBase::m_pValue[i]; } const Type& operator[]( int i ) const { return Get( i ); } #if defined( GAME_DLL ) // Data can only be set on the server Type& operator[]( int i ) { return GetForModify( i ); } Type& GetForModify( int i ) { Assert( i >= 0 && i < m_iCount ); return CSharedArrayBase::m_pValue[i]; } void Set( int i, const Type &val ) { Assert( i >= 0 && i < m_iCount ); CSharedArrayBase::m_pValue[i] = val; } #endif private: virtual void _Save( ISave *pSave ) { SharedVar_Save( pSave, CSharedArrayBase::m_pValue, m_iCount ); } virtual void _Restore( IRestore *pRestore ) { SharedVar_Restore( pRestore, CSharedArrayBase::m_pValue ); } virtual bool _IsEmpty( void ) { return SharedVar_IsEmpty( CSharedArrayBase::m_pValue, m_iCount ); } virtual void _MakeEmpty( void ) { SharedVar_MakeEmpty( CSharedArrayBase::m_pValue, m_iCount ); } public: int m_iCount; }; // Shared handle array wrapper. template< class Type, class Changer > class CSharedHandleArrayBase : public CSharedArrayBase< EHANDLE, Changer > { public: virtual void Shared_Handle_Vars_Must_Use_CSharedHandle_Or_CSharedHandleArray() {} void Initialize( char *pchName, int iEntNum, int iCount ) { Assert( !this->m_pSharedMemory && !(CSharedHandleArrayBase::m_pValue) && iCount > 0 ); this->m_iCount = iCount; this->m_pSharedMemory = engine->GetSinglePlayerSharedMemorySpace( pchName, iEntNum ); this->m_pSharedMemory->Init( sizeof( EHANDLE ) * this->m_iCount + sizeof( int ) * this->m_iCount ); // Also allocate memory for the ints that convert to Client handles this->m_pValue = (EHANDLE*)this->m_pSharedMemory->Base(); m_piClientIndex = (int*)((void*)(CSharedHandleArrayBase::m_pValue + this->m_iCount)); } const int& Count() const { return this->m_iCount; } const Type& Get( int i ) const { Assert( i >= 0 && i < this->m_iCount ); return Get_Internal( i ); } const Type* operator[]( int i ) const { return Get_Internal( i ); } #if defined( GAME_DLL ) // Data can only be set on the server const Type* Set( int i, const Type *val ) { Assert( i >= 0 && i < this->m_iCount ); CSharedHandleArrayBase::m_pValue[i] = val; // Store the int that we'll need to translate to the EHandle on the client m_piClientIndex[i] = Server_EHandleToInt( CSharedHandleArrayBase::m_pValue[i] ); return val; } #endif private: EHANDLE GetHandle_Internal( int i ) const { #if defined( GAME_DLL ) // Server can get the handle directly return CSharedHandleArrayBase::m_pValue[i]; #else // Client needs to get the handle translated from the stroed int EHANDLE hClient = Client_IntToEHandle( m_piClientIndex[i] ); return hClient; #endif } Type* Get_Internal( int i ) const { return static_cast< Type* >( GetHandle_Internal(i).Get() ); } private: void UpdateClientIndices( void ) { for ( int i = 0; i < this->m_iConcept; ++i ) { m_piClientIndex[i] = Server_EHandleToInt( CSharedHandleBase::m_pValue[i] ); } } virtual void _Restore( IRestore *pRestore ) { SharedVar_Restore( pRestore, CSharedHandleArrayBase::m_pValue ); UpdateClientIndices(); } public: int *m_piClientIndex; // Pointer to ints for Client handle translations }; // Prevent Shared Vars from using UtlVector templates without the UtlVector wrapper template< class Type, class Changer > class CSharedVarBase< CUtlVector, Changer > : public ISharedVarBase { public: CSharedVarBase( void ) { m_pSharedMemory = NULL; m_pValue = NULL; } ~CSharedVarBase( void ) { m_pSharedMemory->Release(); m_pSharedMemory = NULL; m_pValue = NULL; } protected: virtual void Shared_CUtlVector_Vars_Must_Use_CSharedUtlVector() = 0; public: ISPSharedMemory *m_pSharedMemory; CUtlVector *m_pValue; }; // Shared UtlVector wrapper. template< class Type, class Changer > class CSharedUtlVectorBase : public CSharedVarBase< CUtlVector, Changer > { public: void Initialize( char *pchName, int iEntNum ) { Assert( !this->m_pSharedMemory && !(CSharedUtlVectorBase::m_pValue) ); this->m_pSharedMemory = engine->GetSinglePlayerSharedMemorySpace( pchName, iEntNum ); this->m_pSharedMemory->Init( sizeof( CUtlVector ) ); CSharedUtlVectorBase::m_pValue = (CUtlVector*)this->m_pSharedMemory->Base(); } #if defined( GAME_DLL ) // Data can only be set on the server operator CUtlVector&() { return *CSharedUtlVectorBase::m_pValue; } CUtlVector& GetForModify() { return *CSharedUtlVectorBase::m_pValue; } CUtlVector* operator->() { return CSharedUtlVectorBase::m_pValue; } Type& operator[]( int i ) { return GetForModify( i ); } Type& GetForModify( int i ) { Assert( i >= 0 && i < (CSharedUtlVectorBase::m_pValue)->Count() ); return (*CSharedUtlVectorBase::m_pValue)[i]; } void Set( int i, const Type &val ) { Assert( i >= 0 && i < (CSharedUtlVectorBase::m_pValue)->Count() ); (*CSharedUtlVectorBase::m_pValue)[i] = val; } #endif operator const CUtlVector&() const { return *CSharedUtlVectorBase::m_pValue; } const CUtlVector& Get() const { return *CSharedUtlVectorBase::m_pValue; } const CUtlVector* operator->() const { return CSharedUtlVectorBase::m_pValue; } const Type& operator[]( int i ) const { return Get( i ); } const Type& Get( int i ) const { Assert( i >= 0 && i < (CSharedUtlVectorBase::m_pValue)->Count() ); return (*CSharedUtlVectorBase::m_pValue)[i]; } const int Count() const { return CSharedUtlVectorBase::m_pValue->Count(); } protected: virtual void Shared_CUtlVector_Vars_Must_Use_CSharedUtlVector() {} private: virtual void _Save( ISave *pSave ) { SharedVar_SaveUtlVector( pSave, CSharedUtlVectorBase::m_pValue, 1 ); } virtual void _Restore( IRestore *pRestore ) { SharedVar_RestoreUtlVector( pRestore, CSharedUtlVectorBase::m_pValue ); } virtual bool _IsEmpty( void ) { return SharedVar_IsEmptyUtlVector( CSharedUtlVectorBase::m_pValue, 1 ); } virtual void _MakeEmpty( void ) { SharedVar_MakeEmptyUtlVector( CSharedUtlVectorBase::m_pValue, 1 ); } }; // Use this macro to define a network variable. #define CSharedVar( type, name ) \ SHARED_VAR_START( type, name ) \ SHARED_VAR_END( type, name, CSharedVarBase ) // Helper for color32's. Contains GetR(), SetR(), etc.. functions. #define CSharedColor32( name ) \ SHARED_VAR_START( color32, name ) \ SHARED_VAR_END( color32, name, CSharedColor32Base ) // Vectors + some convenient helper functions. #define CSharedVector( name ) CSharedVectorInternal( Vector, name ) #define CSharedQAngle( name ) CSharedVectorInternal( QAngle, name ) #define CSharedVectorInternal( type, name ) \ SHARED_VAR_START( type, name ) \ SHARED_VAR_END( type, name, CSharedVectorBase ) #define CSharedQuaternion( name ) \ SHARED_VAR_START( Quaternion, name ) \ SHARED_VAR_END( Quaternion, name, CSharedQuaternionBase ) #define CSharedHandle( handletype, name ) \ SHARED_VAR_START( handletype, name ) \ SHARED_VAR_END( handletype, name, CSharedHandleBase ) #define CSharedArray( type, name, count ) \ SHARED_VAR_START( type, name ) \ SHARED_VAR_END( type, name, CSharedArrayBase ) \ enum { m_SharedArray_count_##name = count }; #define CSharedString( name, length ) \ CSharedArray( char, name, length ) #define CSharedHandleArray( handletype, name, count ) \ SHARED_VAR_START( handletype, name ) \ SHARED_VAR_END( handletype, name, CSharedHandleArrayBase ) \ enum { m_SharedArray_count_##name = count }; #define CSharedUtlVector( utlvectortype, name ) \ SHARED_VAR_START( utlvectortype, name ) \ SHARED_VAR_END( utlvectortype, name, CSharedUtlVectorBase ) \ // Internal macros used in definitions of network vars. #define SHARED_VAR_START( type, name ) \ class SharedVar_##name; \ friend class SharedVar_##name; \ typedef ThisClass MakeASharedVar_##name; \ class SharedVar_##name \ { \ public: \ template friend int ServerClassInit(T *); #define SHARED_VAR_END( type, name, base ) \ }; \ base< type, SharedVar_##name > name; #define DECLARE_SHAREDCLASS() \ virtual void InitSharedVars( void ); #define IMPLEMENT_SHAREDCLASS_DT( type ) \ void type::InitSharedVars( void ) \ { \ BaseClass::InitSharedVars(); #define END_SHARED_TABLE() \ } #define SharedProp( var ) \ var.Initialize( "SharedVar_"#var, entindex() ); #define SharedPropArray( var ) \ var.Initialize( "SharedVar_"#var, entindex(), m_SharedArray_count_##var ); // Save/Restore handling class CSharedVarSaveDataOps : public CDefSaveRestoreOps { // saves the entire array of variables virtual void Save( const SaveRestoreFieldInfo_t &fieldInfo, ISave *pSave ) { ISharedVarBase *pSharedVar = (ISharedVarBase *)fieldInfo.pField; pSharedVar->_Save( pSave ); } // restores a single instance of the variable virtual void Restore( const SaveRestoreFieldInfo_t &fieldInfo, IRestore *pRestore ) { ISharedVarBase *pSharedVar = (ISharedVarBase *)fieldInfo.pField; pSharedVar->_Restore( pRestore ); } virtual bool IsEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) { ISharedVarBase *pSharedVar = (ISharedVarBase *)fieldInfo.pField; return pSharedVar->_IsEmpty(); } virtual void MakeEmpty( const SaveRestoreFieldInfo_t &fieldInfo ) { ISharedVarBase *pSharedVar = (ISharedVarBase *)fieldInfo.pField; return pSharedVar->_MakeEmpty(); } }; static CSharedVarSaveDataOps g_SharedVarSaveDataOps; #define DEFINE_SHARED_FIELD(name) \ { FIELD_CUSTOM, #name, offsetof(classNameTypedef, name), 1, FTYPEDESC_SAVE, NULL, &g_SharedVarSaveDataOps, NULL } #endif // SHAREDVAR_H