|
|
//========= 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<int>::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; } 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 > TEMPLATE_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 > TEMPLATE_STATIC void SharedVar_Restore( IRestore *pRestore, Type *pValue ) { int iNumBytes = pRestore->ReadInt(); pRestore->ReadData( (char*)( (void*)(pValue) ), iNumBytes, 0 ); }
template< class Type > TEMPLATE_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] ) { return false; } }
return true; }
template< class Type > TEMPLATE_STATIC void SharedVar_MakeEmpty( Type *pValue, int iCount = 1 ) { memset( pValue, 0, sizeof( Type ) * iCount ); }
#ifdef GNUC
#define SELECTOR __attribute__((weak))
#else
#define SELECTOR
#endif
// EHANDLE Save/Restore specializations
template<> SELECTOR TEMPLATE_STATIC void SharedVar_Save<EHANDLE>( ISave *pSave, EHANDLE *pValue, int iCount ) { pSave->WriteInt( &iCount ); pSave->WriteEHandle( pValue, iCount ); }
template<> SELECTOR TEMPLATE_STATIC void SharedVar_Restore<EHANDLE>( 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<Type> *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<Type> *pValue ) { int iNumBytes = pRestore->ReadInt(); pValue->SetCount( iNumBytes / sizeof( Type ) ); pRestore->ReadData( (char*)( (void*)(pValue->Base()) ), iNumBytes, 0 ); }
template< class Type > TEMPLATE_STATIC bool SharedVar_IsEmptyUtlVector( CUtlVector<Type> *pValue, int iCount = 1 ) { Assert( iCount == 1 );
return ( pValue->Count() == 0 ); }
template< class Type > TEMPLATE_STATIC void SharedVar_MakeEmptyUtlVector( CUtlVector<Type> *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 ) { if ( m_pSharedMemory ) { 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<const Type>( val ) ); }
template< class C > const Type& operator=( const CNetworkVarBase< C, Changer > &val ) { return Set( static_cast<const Type>( *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<const Type>( val ) ); }
template< class C > const Type& operator-=( const C &val ) { return Set( *m_pValue - static_cast<const Type>( val ) ); }
template< class C > const Type& operator/=( const C &val ) { return Set( *m_pValue / static_cast<const Type>( val ) ); }
template< class C > const Type& operator*=( const C &val ) { return Set( *m_pValue * static_cast<const Type>( val ) ); }
template< class C > const Type& operator^=( const C &val ) { return Set( *m_pValue ^ static_cast<const Type>( val ) ); }
template< class C > const Type& operator|=( const C &val ) { return Set( *m_pValue | static_cast<const Type>( 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<unsigned char> = 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<const Type>( 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<Type>( pSave, m_pValue ); } virtual void _Restore( IRestore *pRestore ) { SharedVar_Restore<Type>( pRestore, m_pValue ); } virtual bool _IsEmpty( void ) { return SharedVar_IsEmpty<Type>( m_pValue ); } virtual void _MakeEmpty( void ) { SharedVar_MakeEmpty<Type>( 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<Type,Changer> &val ) { return CSharedVarBase<Type,Changer>::Set( *val.m_pValue ); }
inline void SetR( byte val ) { SetVal( CSharedColor32Base<Type,Changer>::m_pValue->r, val ); } inline void SetG( byte val ) { SetVal( CSharedColor32Base<Type,Changer>::m_pValue->g, val ); } inline void SetB( byte val ) { SetVal( CSharedColor32Base<Type,Changer>::m_pValue->b, val ); } inline void SetA( byte val ) { SetVal( CSharedColor32Base<Type,Changer>::m_pValue->a, val ); } #endif
inline byte GetR() const { return CSharedColor32Base<Type,Changer>::m_pValue->r; } inline byte GetG() const { return CSharedColor32Base<Type,Changer>::m_pValue->g; } inline byte GetB() const { return CSharedColor32Base<Type,Changer>::m_pValue->b; } inline byte GetA() const { return CSharedColor32Base<Type,Changer>::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<Type,Changer> &val ) { return CSharedVarBase<Type,Changer>::Set( *val.m_pValue ); }
inline void SetX( float val ) { SetVal( CSharedVectorBase<Type,Changer>::m_pValue->x, val ); } inline void SetY( float val ) { SetVal( CSharedVectorBase<Type,Changer>::m_pValue->y, val ); } inline void SetZ( float val ) { SetVal( CSharedVectorBase<Type,Changer>::m_pValue->z, val ); } inline void Set( int i, float val ) { SetVal( (*CSharedVectorBase<Type,Changer>::m_pValue)[i], val ); } inline float& operator[]( int i ) { return (*CSharedVectorBase<Type,Changer>::m_pValue)[i]; }
const Type& operator*=( float val ) { return CSharedVarBase< Type, Changer >::Set( (*CSharedVectorBase<Type,Changer>::m_pValue) * val ); } #endif
inline float GetX() const { return CSharedVectorBase<Type,Changer>::m_pValue->x; } inline float GetY() const { return CSharedVectorBase<Type,Changer>::m_pValue->y; } inline float GetZ() const { return CSharedVectorBase<Type,Changer>::m_pValue->z; } inline const float& operator[]( int i ) const { return (*CSharedVectorBase<Type,Changer>::m_pValue)[i]; }
bool operator==( const Type &val ) const { return (*CSharedVectorBase<Type,Changer>::m_pValue) == (Type)val; }
bool operator!=( const Type &val ) const { return (*CSharedVectorBase<Type,Changer>::m_pValue) != (Type)val; }
const Type operator+( const Type &val ) const { return (*CSharedVectorBase<Type,Changer>::m_pValue) + val; }
const Type operator-( const Type &val ) const { return (*CSharedVectorBase<Type,Changer>::m_pValue) - val; }
const Type operator*( const Type &val ) const { return (*CSharedVectorBase<Type,Changer>::m_pValue) * val; }
const Type operator*( float val ) const { return (*CSharedVectorBase<Type,Changer>::m_pValue) * val; }
const Type operator/( const Type &val ) const { return (*CSharedVectorBase<Type,Changer>::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<Type,Changer> &val ) { return CSharedVarBase<Type,Changer>::Set( *val.m_pValue ); }
const Type& operator*=( float val ) { return CSharedVarBase< Type, Changer >::Set( (*CSharedQuaternionBase<Type,Changer>::m_pValue) * val ); }
inline void SetX( float val ) { SetVar( CSharedQuaternionBase<Type,Changer>::m_pValue->x, val ); } inline void SetY( float val ) { SetVar( CSharedQuaternionBase<Type,Changer>::m_pValue->y, val ); } inline void SetZ( float val ) { SetVar( CSharedQuaternionBase<Type,Changer>::m_pValue->z, val ); } inline void SetW( float val ) { SetVar( CSharedQuaternionBase<Type,Changer>::m_pValue->w, val ); } inline void Set( int i, float val ) { SetVar( (*CSharedQuaternionBase<Type,Changer>::m_pValue)[i], val ); } inline float& operator[]( int i ) { return (*CSharedQuaternionBase<Type,Changer>::m_pValue)[i]; } #endif
inline float GetX() const { return CSharedQuaternionBase<Type,Changer>::m_pValue->x; } inline float GetY() const { return CSharedQuaternionBase<Type,Changer>::m_pValue->y; } inline float GetZ() const { return CSharedQuaternionBase<Type,Changer>::m_pValue->z; } inline float GetW() const { return CSharedQuaternionBase<Type,Changer>::m_pValue->w; } inline const float& operator[]( int i ) const { return (*CSharedQuaternionBase<Type,Changer>::m_pValue)[i]; }
bool operator==( const Type &val ) const { return (*CSharedQuaternionBase<Type,Changer>::m_pValue) == (Type)val; }
bool operator!=( const Type &val ) const { return (*CSharedQuaternionBase<Type,Changer>::m_pValue) != (Type)val; }
const Type operator+( const Type &val ) const { return (*CSharedQuaternionBase<Type,Changer>::m_pValue) + val; }
const Type operator-( const Type &val ) const { return (*CSharedQuaternionBase<Type,Changer>::m_pValue) - val; }
const Type operator*( const Type &val ) const { return (*CSharedQuaternionBase<Type,Changer>::m_pValue) * val; }
const Type operator*( float val ) const { return (*CSharedQuaternionBase<Type,Changer>::m_pValue) * val; }
const Type operator/( const Type &val ) const { return (*CSharedQuaternionBase<Type,Changer>::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<Type>, Changer > : public ISharedVarBase { public: CSharedVarBase( void ) { m_pSharedMemory = NULL; m_pValue = NULL; }
~CSharedVarBase( void ) { if ( m_pSharedMemory ) { 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<Type> *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 ) { if ( m_pSharedMemory ) { 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<Type,Changer> &val ) { const EHANDLE &handle = CSharedVarBase<EHANDLE,Changer>::Set( *val.m_pValue ); return *(const Type*)handle.Get(); }
const Type* Set( const Type *val ) { (*CSharedHandleBase<Type,Changer>::m_pValue) = val;
// Store the int that we'll need to translate to the EHandle on the client
*m_piClientIndex = Server_EHandleToInt( *CSharedHandleBase<Type,Changer>::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<Type,Changer>::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<Type,Changer>::m_pValue) ); }
virtual void _Save( ISave *pSave ) { SharedVar_Save<EHANDLE>( pSave, this->m_pValue ); }
virtual void _Restore( IRestore *pRestore ) { SharedVar_Restore<EHANDLE>( pRestore, this->m_pValue ); UpdateClientIndex(); }
virtual bool _IsEmpty( void ) { return SharedVar_IsEmpty<EHANDLE>( this->m_pValue ); }
virtual void _MakeEmpty( void ) { SharedVar_MakeEmpty<EHANDLE>( 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<Type,Changer>::m_pValue) && iCount > 0 );
m_iCount = iCount; this->m_pSharedMemory = engine->GetSinglePlayerSharedMemorySpace( pchName, iEntNum ); this->m_pSharedMemory->Init( sizeof( Type ) * m_iCount ); CSharedArrayBase<Type,Changer>::m_pValue = (Type*)this->m_pSharedMemory->Base(); }
const int& Count() const { return m_iCount; }
const Type* Get() const { return CSharedArrayBase<Type,Changer>::m_pValue; }
const Type& Get( int i ) const { Assert( i >= 0 && i < m_iCount ); return CSharedArrayBase<Type,Changer>::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<Type,Changer>::m_pValue[i]; }
void Set( int i, const Type &val ) { Assert( i >= 0 && i < m_iCount ); CSharedArrayBase<Type,Changer>::m_pValue[i] = val; } #endif
private: virtual void _Save( ISave *pSave ) { SharedVar_Save<Type>( pSave, CSharedArrayBase<Type,Changer>::m_pValue, m_iCount ); }
virtual void _Restore( IRestore *pRestore ) { SharedVar_Restore<Type>( pRestore, CSharedArrayBase<Type,Changer>::m_pValue ); }
virtual bool _IsEmpty( void ) { return SharedVar_IsEmpty<Type>( CSharedArrayBase<Type,Changer>::m_pValue, m_iCount ); }
virtual void _MakeEmpty( void ) { SharedVar_MakeEmpty<Type>( CSharedArrayBase<Type,Changer>::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<Type,Changer>::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<Type,Changer>::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<Type,Changer>::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<Type,Changer>::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<Type,Changer>::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<Type,Changer>::m_pValue[i] ); } }
virtual void _Restore( IRestore *pRestore ) { SharedVar_Restore<EHANDLE>( pRestore, CSharedHandleArrayBase<Type,Changer>::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<Type>, Changer > : public ISharedVarBase { public: CSharedVarBase( void ) { m_pSharedMemory = NULL; m_pValue = NULL; }
~CSharedVarBase( void ) { if ( m_pSharedMemory ) { m_pSharedMemory->Release(); m_pSharedMemory = NULL; } m_pValue = NULL; }
protected: virtual void Shared_CUtlVector_Vars_Must_Use_CSharedUtlVector() = 0;
public: ISPSharedMemory *m_pSharedMemory; CUtlVector<Type> *m_pValue; };
// Shared UtlVector wrapper.
template< class Type, class Changer > class CSharedUtlVectorBase : public CSharedVarBase< CUtlVector<Type>, Changer > { public: void Initialize( char *pchName, int iEntNum ) { Assert( !this->m_pSharedMemory && !(CSharedUtlVectorBase<Type,Changer>::m_pValue) );
this->m_pSharedMemory = engine->GetSinglePlayerSharedMemorySpace( pchName, iEntNum ); this->m_pSharedMemory->Init( sizeof( CUtlVector<Type> ) ); CSharedUtlVectorBase<Type,Changer>::m_pValue = (CUtlVector<Type>*)this->m_pSharedMemory->Base(); }
#if defined( GAME_DLL )
// Data can only be set on the server
operator CUtlVector<Type>&() { return *CSharedUtlVectorBase<Type,Changer>::m_pValue; }
CUtlVector<Type>& GetForModify() { return *CSharedUtlVectorBase<Type,Changer>::m_pValue; }
CUtlVector<Type>* operator->() { return CSharedUtlVectorBase<Type,Changer>::m_pValue; }
Type& operator[]( int i ) { return GetForModify( i ); }
Type& GetForModify( int i ) { Assert( i >= 0 && i < (CSharedUtlVectorBase<Type,Changer>::m_pValue)->Count() ); return (*CSharedUtlVectorBase<Type,Changer>::m_pValue)[i]; }
void Set( int i, const Type &val ) { Assert( i >= 0 && i < (CSharedUtlVectorBase<Type,Changer>::m_pValue)->Count() ); (*CSharedUtlVectorBase<Type,Changer>::m_pValue)[i] = val; } #endif
operator const CUtlVector<Type>&() const { return *CSharedUtlVectorBase<Type,Changer>::m_pValue; }
const CUtlVector<Type>& Get() const { return *CSharedUtlVectorBase<Type,Changer>::m_pValue; }
const CUtlVector<Type>* operator->() const { return CSharedUtlVectorBase<Type,Changer>::m_pValue; }
const Type& operator[]( int i ) const { return Get( i ); }
const Type& Get( int i ) const { Assert( i >= 0 && i < (CSharedUtlVectorBase<Type,Changer>::m_pValue)->Count() ); return (*CSharedUtlVectorBase<Type,Changer>::m_pValue)[i]; }
const int Count() const { return CSharedUtlVectorBase<Type,Changer>::m_pValue->Count(); }
protected: virtual void Shared_CUtlVector_Vars_Must_Use_CSharedUtlVector() {}
private: virtual void _Save( ISave *pSave ) { SharedVar_SaveUtlVector<Type>( pSave, CSharedUtlVectorBase<Type,Changer>::m_pValue, 1 ); }
virtual void _Restore( IRestore *pRestore ) { SharedVar_RestoreUtlVector<Type>( pRestore, CSharedUtlVectorBase<Type,Changer>::m_pValue ); }
virtual bool _IsEmpty( void ) { return SharedVar_IsEmptyUtlVector<Type>( CSharedUtlVectorBase<Type,Changer>::m_pValue, 1 ); }
virtual void _MakeEmpty( void ) { SharedVar_MakeEmptyUtlVector<Type>( CSharedUtlVectorBase<Type,Changer>::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 <typename T> 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
|