You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1144 lines
28 KiB
1144 lines
28 KiB
//========= 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_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<EHANDLE>( ISave *pSave, EHANDLE *pValue, int iCount ) |
|
{ |
|
pSave->WriteInt( &iCount ); |
|
pSave->WriteEHandle( pValue, iCount ); |
|
} |
|
|
|
template<> |
|
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 > |
|
static bool SharedVar_IsEmptyUtlVector( CUtlVector<Type> *pValue, int iCount = 1 ) |
|
{ |
|
Assert( iCount == 1 ); |
|
|
|
return ( pValue->Count() == 0 ); |
|
} |
|
|
|
template< class Type > |
|
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 ) |
|
{ |
|
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 ) |
|
{ |
|
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 ) |
|
{ |
|
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 ) |
|
{ |
|
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
|
|
|