source-engine/game/shared/sharedvar.h
2023-10-03 17:23:56 +03:00

1145 lines
28 KiB
C++

//========= 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