diff options
Diffstat (limited to 'public/dt_send.h')
| -rw-r--r-- | public/dt_send.h | 808 |
1 files changed, 808 insertions, 0 deletions
diff --git a/public/dt_send.h b/public/dt_send.h new file mode 100644 index 0000000..f591c15 --- /dev/null +++ b/public/dt_send.h @@ -0,0 +1,808 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#ifndef DATATABLE_SEND_H +#define DATATABLE_SEND_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "dt_common.h" +#include "tier0/dbg.h" +#include "const.h" +#include "bitvec.h" + + +// ------------------------------------------------------------------------ // +// Send proxies can be used to convert a variable into a networkable type +// (a good example is converting an edict pointer into an integer index). + +// These allow you to translate data. For example, if you had a user-entered +// string number like "10" (call the variable pUserStr) and wanted to encode +// it as an integer, you would use a SendPropInt32 and write a proxy that said: +// pOut->m_Int = atoi(pUserStr); + +// pProp : the SendProp that has the proxy +// pStructBase : the base structure (like CBaseEntity*). +// pData : the address of the variable to proxy. +// pOut : where to output the proxied value. +// iElement : the element index if this data is part of an array (or 0 if not). +// objectID : entity index for debugging purposes. + +// Return false if you don't want the engine to register and send a delta to +// the clients for this property (regardless of whether it actually changed or not). +// ------------------------------------------------------------------------ // +typedef void (*SendVarProxyFn)( const SendProp *pProp, const void *pStructBase, const void *pData, DVariant *pOut, int iElement, int objectID ); + +// Return the pointer to the data for the datatable. +// If the proxy returns null, it's the same as if pRecipients->ClearAllRecipients() was called. +class CSendProxyRecipients; + +typedef void* (*SendTableProxyFn)( + const SendProp *pProp, + const void *pStructBase, + const void *pData, + CSendProxyRecipients *pRecipients, + int objectID ); + + +class CNonModifiedPointerProxy +{ +public: + CNonModifiedPointerProxy( SendTableProxyFn fn ); + +public: + + SendTableProxyFn m_Fn; + CNonModifiedPointerProxy *m_pNext; +}; + + +// This tells the engine that the send proxy will not modify the pointer +// - it only plays with the recipients. This must be set on proxies that work +// this way, otherwise the engine can't track which properties changed +// in NetworkStateChanged(). +#define REGISTER_SEND_PROXY_NON_MODIFIED_POINTER( sendProxyFn ) static CNonModifiedPointerProxy __proxy_##sendProxyFn( sendProxyFn ); + + +class CStandardSendProxiesV1 +{ +public: + CStandardSendProxiesV1(); + + SendVarProxyFn m_Int8ToInt32; + SendVarProxyFn m_Int16ToInt32; + SendVarProxyFn m_Int32ToInt32; + + SendVarProxyFn m_UInt8ToInt32; + SendVarProxyFn m_UInt16ToInt32; + SendVarProxyFn m_UInt32ToInt32; + + SendVarProxyFn m_FloatToFloat; + SendVarProxyFn m_VectorToVector; + +#ifdef SUPPORTS_INT64 + SendVarProxyFn m_Int64ToInt64; + SendVarProxyFn m_UInt64ToInt64; +#endif +}; + +class CStandardSendProxies : public CStandardSendProxiesV1 +{ +public: + CStandardSendProxies(); + + SendTableProxyFn m_DataTableToDataTable; + SendTableProxyFn m_SendLocalDataTable; + CNonModifiedPointerProxy **m_ppNonModifiedPointerProxies; +}; + +extern CStandardSendProxies g_StandardSendProxies; + + +// Max # of datatable send proxies you can have in a tree. +#define MAX_DATATABLE_PROXIES 32 + +// ------------------------------------------------------------------------ // +// Datatable send proxies are used to tell the engine where the datatable's +// data is and to specify which clients should get the data. +// +// pRecipients is the object that allows you to specify which clients will +// receive the data. +// ------------------------------------------------------------------------ // +class CSendProxyRecipients +{ +public: + void SetAllRecipients(); // Note: recipients are all set by default when each proxy is called. + void ClearAllRecipients(); + + void SetRecipient( int iClient ); // Note: these are CLIENT indices, not entity indices (so the first player's index is 0). + void ClearRecipient( int iClient ); + + // Clear all recipients and set only the specified one. + void SetOnly( int iClient ); + +public: + // Make sure we have enough room for the max possible player count + CBitVec< ABSOLUTE_PLAYER_LIMIT > m_Bits; +}; + +inline void CSendProxyRecipients::SetAllRecipients() +{ + m_Bits.SetAll(); +} + +inline void CSendProxyRecipients::ClearAllRecipients() +{ + m_Bits.ClearAll(); +} + +inline void CSendProxyRecipients::SetRecipient( int iClient ) +{ + m_Bits.Set( iClient ); +} + +inline void CSendProxyRecipients::ClearRecipient( int iClient ) +{ + m_Bits.Clear( iClient ); +} + +inline void CSendProxyRecipients::SetOnly( int iClient ) +{ + m_Bits.ClearAll(); + m_Bits.Set( iClient ); +} + + + +// ------------------------------------------------------------------------ // +// ArrayLengthSendProxies are used when you want to specify an array's length +// dynamically. +// ------------------------------------------------------------------------ // +typedef int (*ArrayLengthSendProxyFn)( const void *pStruct, int objectID ); + + + +class RecvProp; +class SendTable; +class CSendTablePrecalc; + + +// -------------------------------------------------------------------------------------------------------------- // +// SendProp. +// -------------------------------------------------------------------------------------------------------------- // + +// If SendProp::GetDataTableProxyIndex() returns this, then the proxy is one that always sends +// the data to all clients, so we don't need to store the results. +#define DATATABLE_PROXY_INDEX_NOPROXY 255 +#define DATATABLE_PROXY_INDEX_INVALID 254 + +class SendProp +{ +public: + SendProp(); + virtual ~SendProp(); + + void Clear(); + + int GetOffset() const; + void SetOffset( int i ); + + SendVarProxyFn GetProxyFn() const; + void SetProxyFn( SendVarProxyFn f ); + + SendTableProxyFn GetDataTableProxyFn() const; + void SetDataTableProxyFn( SendTableProxyFn f ); + + SendTable* GetDataTable() const; + void SetDataTable( SendTable *pTable ); + + char const* GetExcludeDTName() const; + + // If it's one of the numbered "000", "001", etc properties in an array, then + // these can be used to get its array property name for debugging. + const char* GetParentArrayPropName() const; + void SetParentArrayPropName( char *pArrayPropName ); + + const char* GetName() const; + + bool IsSigned() const; + + bool IsExcludeProp() const; + + bool IsInsideArray() const; // Returns true if SPROP_INSIDEARRAY is set. + void SetInsideArray(); + + // Arrays only. + void SetArrayProp( SendProp *pProp ); + SendProp* GetArrayProp() const; + + // Arrays only. + void SetArrayLengthProxy( ArrayLengthSendProxyFn fn ); + ArrayLengthSendProxyFn GetArrayLengthProxy() const; + + int GetNumElements() const; + void SetNumElements( int nElements ); + + // Return the # of bits to encode an array length (must hold GetNumElements()). + int GetNumArrayLengthBits() const; + + int GetElementStride() const; + + SendPropType GetType() const; + + int GetFlags() const; + void SetFlags( int flags ); + + // Some property types bind more data to the SendProp in here. + const void* GetExtraData() const; + void SetExtraData( const void *pData ); + +public: + + RecvProp *m_pMatchingRecvProp; // This is temporary and only used while precalculating + // data for the decoders. + + SendPropType m_Type; + int m_nBits; + float m_fLowValue; + float m_fHighValue; + + SendProp *m_pArrayProp; // If this is an array, this is the property that defines each array element. + ArrayLengthSendProxyFn m_ArrayLengthProxy; // This callback returns the array length. + + int m_nElements; // Number of elements in the array (or 1 if it's not an array). + int m_ElementStride; // Pointer distance between array elements. + + const char *m_pExcludeDTName; // If this is an exclude prop, then this is the name of the datatable to exclude a prop from. + const char *m_pParentArrayPropName; + + const char *m_pVarName; + float m_fHighLowMul; + +private: + + int m_Flags; // SPROP_ flags. + + SendVarProxyFn m_ProxyFn; // NULL for DPT_DataTable. + SendTableProxyFn m_DataTableProxyFn; // Valid for DPT_DataTable. + + SendTable *m_pDataTable; + + // SENDPROP_VECTORELEM makes this negative to start with so we can detect that and + // set the SPROP_IS_VECTOR_ELEM flag. + int m_Offset; + + // Extra data bound to this property. + const void *m_pExtraData; +}; + + +inline int SendProp::GetOffset() const +{ + return m_Offset; +} + +inline void SendProp::SetOffset( int i ) +{ + m_Offset = i; +} + +inline SendVarProxyFn SendProp::GetProxyFn() const +{ + Assert( m_Type != DPT_DataTable ); + return m_ProxyFn; +} + +inline void SendProp::SetProxyFn( SendVarProxyFn f ) +{ + m_ProxyFn = f; +} + +inline SendTableProxyFn SendProp::GetDataTableProxyFn() const +{ + Assert( m_Type == DPT_DataTable ); + return m_DataTableProxyFn; +} + +inline void SendProp::SetDataTableProxyFn( SendTableProxyFn f ) +{ + m_DataTableProxyFn = f; +} + +inline SendTable* SendProp::GetDataTable() const +{ + return m_pDataTable; +} + +inline void SendProp::SetDataTable( SendTable *pTable ) +{ + m_pDataTable = pTable; +} + +inline char const* SendProp::GetExcludeDTName() const +{ + return m_pExcludeDTName; +} + +inline const char* SendProp::GetParentArrayPropName() const +{ + return m_pParentArrayPropName; +} + +inline void SendProp::SetParentArrayPropName( char *pArrayPropName ) +{ + Assert( !m_pParentArrayPropName ); + m_pParentArrayPropName = pArrayPropName; +} + +inline const char* SendProp::GetName() const +{ + return m_pVarName; +} + + +inline bool SendProp::IsSigned() const +{ + return !(m_Flags & SPROP_UNSIGNED); +} + +inline bool SendProp::IsExcludeProp() const +{ + return (m_Flags & SPROP_EXCLUDE) != 0; +} + +inline bool SendProp::IsInsideArray() const +{ + return (m_Flags & SPROP_INSIDEARRAY) != 0; +} + +inline void SendProp::SetInsideArray() +{ + m_Flags |= SPROP_INSIDEARRAY; +} + +inline void SendProp::SetArrayProp( SendProp *pProp ) +{ + m_pArrayProp = pProp; +} + +inline SendProp* SendProp::GetArrayProp() const +{ + return m_pArrayProp; +} + +inline void SendProp::SetArrayLengthProxy( ArrayLengthSendProxyFn fn ) +{ + m_ArrayLengthProxy = fn; +} + +inline ArrayLengthSendProxyFn SendProp::GetArrayLengthProxy() const +{ + return m_ArrayLengthProxy; +} + +inline int SendProp::GetNumElements() const +{ + return m_nElements; +} + +inline void SendProp::SetNumElements( int nElements ) +{ + m_nElements = nElements; +} + +inline int SendProp::GetElementStride() const +{ + return m_ElementStride; +} + +inline SendPropType SendProp::GetType() const +{ + return m_Type; +} + +inline int SendProp::GetFlags() const +{ + return m_Flags; +} + +inline void SendProp::SetFlags( int flags ) +{ + // Make sure they're using something from the valid set of flags. + Assert( !( flags & ~((1 << SPROP_NUMFLAGBITS) - 1) ) ); + m_Flags = flags; +} + +inline const void* SendProp::GetExtraData() const +{ + return m_pExtraData; +} + +inline void SendProp::SetExtraData( const void *pData ) +{ + m_pExtraData = pData; +} + + +// -------------------------------------------------------------------------------------------------------------- // +// SendTable. +// -------------------------------------------------------------------------------------------------------------- // + +class SendTable +{ +public: + + typedef SendProp PropType; + + SendTable(); + SendTable( SendProp *pProps, int nProps, const char *pNetTableName ); + ~SendTable(); + + void Construct( SendProp *pProps, int nProps, const char *pNetTableName ); + + const char* GetName() const; + + int GetNumProps() const; + SendProp* GetProp( int i ); + + // Used by the engine. + bool IsInitialized() const; + void SetInitialized( bool bInitialized ); + + // Used by the engine while writing info into the signon. + void SetWriteFlag(bool bHasBeenWritten); + bool GetWriteFlag() const; + + bool HasPropsEncodedAgainstTickCount() const; + void SetHasPropsEncodedAgainstTickcount( bool bState ); + +public: + + SendProp *m_pProps; + int m_nProps; + + const char *m_pNetTableName; // The name matched between client and server. + + // The engine hooks the SendTable here. + CSendTablePrecalc *m_pPrecalc; + + +protected: + bool m_bInitialized : 1; + bool m_bHasBeenWritten : 1; + bool m_bHasPropsEncodedAgainstCurrentTickCount : 1; // m_flSimulationTime and m_flAnimTime, e.g. +}; + + +inline const char* SendTable::GetName() const +{ + return m_pNetTableName; +} + + +inline int SendTable::GetNumProps() const +{ + return m_nProps; +} + + +inline SendProp* SendTable::GetProp( int i ) +{ + Assert( i >= 0 && i < m_nProps ); + return &m_pProps[i]; +} + + +inline bool SendTable::IsInitialized() const +{ + return m_bInitialized; +} + + +inline void SendTable::SetInitialized( bool bInitialized ) +{ + m_bInitialized = bInitialized; +} + + +inline bool SendTable::GetWriteFlag() const +{ + return m_bHasBeenWritten; +} + + +inline void SendTable::SetWriteFlag(bool bHasBeenWritten) +{ + m_bHasBeenWritten = bHasBeenWritten; +} + +inline bool SendTable::HasPropsEncodedAgainstTickCount() const +{ + return m_bHasPropsEncodedAgainstCurrentTickCount; +} + +inline void SendTable::SetHasPropsEncodedAgainstTickcount( bool bState ) +{ + m_bHasPropsEncodedAgainstCurrentTickCount = bState; +} + +// ------------------------------------------------------------------------------------------------------ // +// Use BEGIN_SEND_TABLE if you want to declare a SendTable and have it inherit all the properties from +// its base class. There are two requirements for this to work: + +// 1. Its base class must have a static SendTable pointer member variable called m_pClassSendTable which +// points to its send table. The DECLARE_SERVERCLASS and IMPLEMENT_SERVERCLASS macros do this automatically. + +// 2. Your class must typedef its base class as BaseClass. So it would look like this: +// class Derived : public CBaseEntity +// { +// typedef CBaseEntity BaseClass; +// }; + +// If you don't want to interit a base class's properties, use BEGIN_SEND_TABLE_NOBASE. +// ------------------------------------------------------------------------------------------------------ // +#define BEGIN_SEND_TABLE(className, tableName) \ + BEGIN_SEND_TABLE_NOBASE(className, tableName) \ + SendPropDataTable("baseclass", 0, className::BaseClass::m_pClassSendTable, SendProxy_DataTableToDataTable), + +#define BEGIN_SEND_TABLE_NOBASE(className, tableName) \ + template <typename T> int ServerClassInit(T *); \ + namespace tableName { \ + struct ignored; \ + } \ + template <> int ServerClassInit<tableName::ignored>(tableName::ignored *); \ + namespace tableName { \ + SendTable g_SendTable;\ + int g_SendTableInit = ServerClassInit((tableName::ignored *)NULL); \ + } \ + template <> int ServerClassInit<tableName::ignored>(tableName::ignored *) \ + { \ + typedef className currentSendDTClass; \ + static const char *g_pSendTableName = #tableName; \ + SendTable &sendTable = tableName::g_SendTable; \ + static SendProp g_SendProps[] = { \ + SendPropInt("should_never_see_this", 0, sizeof(int)), // It adds a dummy property at the start so you can define "empty" SendTables. + +#define END_SEND_TABLE() \ + };\ + sendTable.Construct(g_SendProps+1, sizeof(g_SendProps) / sizeof(SendProp) - 1, g_pSendTableName);\ + return 1; \ + } + +// Normal offset of is invalid on non-array-types, this is dubious as hell. The rest of the codebase converted to the +// legit offsetof from the C headers, so we'll use the old impl here to avoid exposing temptation to others +#define _hacky_dtsend_offsetof(s,m) ((size_t)&(((s *)0)->m)) + +// These can simplify creating the variables. +// Note: currentSendDTClass::MakeANetworkVar_##varName equates to currentSendDTClass. It's +// there as a check to make sure all networked variables use the CNetworkXXXX macros in network_var.h. +#define SENDINFO(varName) #varName, _hacky_dtsend_offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName), sizeof(((currentSendDTClass*)0)->varName) +#define SENDINFO_ARRAY(varName) #varName, _hacky_dtsend_offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName), sizeof(((currentSendDTClass*)0)->varName[0]) +#define SENDINFO_ARRAY3(varName) #varName, _hacky_dtsend_offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName), sizeof(((currentSendDTClass*)0)->varName[0]), sizeof(((currentSendDTClass*)0)->varName)/sizeof(((currentSendDTClass*)0)->varName[0]) +#define SENDINFO_ARRAYELEM(varName, i) #varName "[" #i "]", _hacky_dtsend_offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName[i]), sizeof(((currentSendDTClass*)0)->varName[0]) +#define SENDINFO_NETWORKARRAYELEM(varName, i)#varName "[" #i "]", _hacky_dtsend_offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName.m_Value[i]), sizeof(((currentSendDTClass*)0)->varName.m_Value[0]) + +// NOTE: Be VERY careful to specify any other vector elems for the same vector IN ORDER and +// right after each other, otherwise it might miss the Y or Z component in SP. +// +// Note: this macro specifies a negative offset so the engine can detect it and setup m_pNext +#define SENDINFO_VECTORELEM(varName, i) #varName "[" #i "]", -(int)_hacky_dtsend_offsetof(currentSendDTClass::MakeANetworkVar_##varName, varName.m_Value[i]), sizeof(((currentSendDTClass*)0)->varName.m_Value[0]) + +#define SENDINFO_STRUCTELEM(varName) #varName, _hacky_dtsend_offsetof(currentSendDTClass, varName), sizeof(((currentSendDTClass*)0)->varName.m_Value) +#define SENDINFO_STRUCTARRAYELEM(varName, i)#varName "[" #i "]", _hacky_dtsend_offsetof(currentSendDTClass, varName.m_Value[i]), sizeof(((currentSendDTClass*)0)->varName.m_Value[0]) + +// Use this when you're not using a CNetworkVar to represent the data you're sending. +#define SENDINFO_NOCHECK(varName) #varName, _hacky_dtsend_offsetof(currentSendDTClass, varName), sizeof(((currentSendDTClass*)0)->varName) +#define SENDINFO_STRING_NOCHECK(varName) #varName, _hacky_dtsend_offsetof(currentSendDTClass, varName) +#define SENDINFO_DT(varName) #varName, _hacky_dtsend_offsetof(currentSendDTClass, varName) +#define SENDINFO_DT_NAME(varName, remoteVarName) #remoteVarName, _hacky_dtsend_offsetof(currentSendDTClass, varName) +#define SENDINFO_NAME(varName,remoteVarName) #remoteVarName, _hacky_dtsend_offsetof(currentSendDTClass, varName), sizeof(((currentSendDTClass*)0)->varName) + +// ------------------------------------------------------------------------ // +// Built-in proxy types. +// See the definition of SendVarProxyFn for information about these. +// ------------------------------------------------------------------------ // +void SendProxy_QAngles ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +void SendProxy_AngleToFloat ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +void SendProxy_FloatToFloat ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +void SendProxy_VectorToVector ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +void SendProxy_VectorXYToVectorXY( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +#if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!! +void SendProxy_QuaternionToQuaternion( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +#endif + +void SendProxy_Int8ToInt32 ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +void SendProxy_Int16ToInt32 ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +void SendProxy_Int32ToInt32 ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +#ifdef SUPPORTS_INT64 +void SendProxy_Int64ToInt64 ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +#endif +void SendProxy_StringToString ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); + +// pData is the address of a data table. +void* SendProxy_DataTableToDataTable( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ); + +// pData is the address of a pointer to a data table. +void* SendProxy_DataTablePtrToDataTable( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ); + +// Used on player entities - only sends the data to the local player (objectID-1). +void* SendProxy_SendLocalDataTable( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ); + + +// ------------------------------------------------------------------------ // +// Use these functions to setup your data tables. +// ------------------------------------------------------------------------ // +SendProp SendPropFloat( + const char *pVarName, // Variable name. + int offset, // Offset into container structure. + int sizeofVar=SIZEOF_IGNORE, + int nBits=32, // Number of bits to use when encoding. + int flags=0, + float fLowValue=0.0f, // For floating point, low and high values. + float fHighValue=HIGH_DEFAULT, // High value. If HIGH_DEFAULT, it's (1<<nBits). + SendVarProxyFn varProxy=SendProxy_FloatToFloat + ); + +SendProp SendPropVector( + const char *pVarName, + int offset, + int sizeofVar=SIZEOF_IGNORE, + int nBits=32, // Number of bits (for each floating-point component) to use when encoding. + int flags=SPROP_NOSCALE, + float fLowValue=0.0f, // For floating point, low and high values. + float fHighValue=HIGH_DEFAULT, // High value. If HIGH_DEFAULT, it's (1<<nBits). + SendVarProxyFn varProxy=SendProxy_VectorToVector + ); + +SendProp SendPropVectorXY( + const char *pVarName, + int offset, + int sizeofVar=SIZEOF_IGNORE, + int nBits=32, // Number of bits (for each floating-point component) to use when encoding. + int flags=SPROP_NOSCALE, + float fLowValue=0.0f, // For floating point, low and high values. + float fHighValue=HIGH_DEFAULT, // High value. If HIGH_DEFAULT, it's (1<<nBits). + SendVarProxyFn varProxy=SendProxy_VectorXYToVectorXY + ); + +#if 0 // We can't ship this since it changes the size of DTVariant to be 20 bytes instead of 16 and that breaks MODs!!! +SendProp SendPropQuaternion( + const char *pVarName, + int offset, + int sizeofVar=SIZEOF_IGNORE, + int nBits=32, // Number of bits (for each floating-point component) to use when encoding. + int flags=SPROP_NOSCALE, + float fLowValue=0.0f, // For floating point, low and high values. + float fHighValue=HIGH_DEFAULT, // High value. If HIGH_DEFAULT, it's (1<<nBits). + SendVarProxyFn varProxy=SendProxy_QuaternionToQuaternion + ); +#endif + +SendProp SendPropAngle( + const char *pVarName, + int offset, + int sizeofVar=SIZEOF_IGNORE, + int nBits=32, + int flags=0, + SendVarProxyFn varProxy=SendProxy_AngleToFloat + ); + +SendProp SendPropQAngles( + const char *pVarName, + int offset, + int sizeofVar=SIZEOF_IGNORE, + int nBits=32, + int flags=0, + SendVarProxyFn varProxy=SendProxy_QAngles + ); + +SendProp SendPropInt( + const char *pVarName, + int offset, + int sizeofVar=SIZEOF_IGNORE, // Handled by SENDINFO macro. + int nBits=-1, // Set to -1 to automatically pick (max) number of bits based on size of element. + int flags=0, + SendVarProxyFn varProxy=0 + ); + +inline SendProp SendPropModelIndex( const char *pVarName, int offset, int sizeofVar=SIZEOF_IGNORE ) +{ + return SendPropInt( pVarName, offset, sizeofVar, SP_MODEL_INDEX_BITS, 0 ); +} + +SendProp SendPropString( + const char *pVarName, + int offset, + int bufferLen, + int flags=0, + SendVarProxyFn varProxy=SendProxy_StringToString); + +// The data table encoder looks at DVariant::m_pData. +SendProp SendPropDataTable( + const char *pVarName, + int offset, + SendTable *pTable, + SendTableProxyFn varProxy=SendProxy_DataTableToDataTable + ); + +SendProp SendPropArray3( + const char *pVarName, + int offset, + int sizeofVar, + int elements, + SendProp pArrayProp, + SendTableProxyFn varProxy=SendProxy_DataTableToDataTable + ); + + + +// Use the macro to let it automatically generate a table name. You shouldn't +// ever need to reference the table name. If you want to exclude this array, then +// reference the name of the variable in varTemplate. +SendProp InternalSendPropArray( + const int elementCount, + const int elementStride, + const char *pName, + ArrayLengthSendProxyFn proxy + ); + + +// Use this and pass the array name and it will figure out the count and stride automatically. +#define SendPropArray( varTemplate, arrayName ) \ + SendPropVariableLengthArray( \ + 0, \ + varTemplate, \ + arrayName ) + +// +// Use this when you want to send a variable-length array of data but there is no physical array you can point it at. +// You need to provide: +// 1. A proxy function that returns the current length of the array. +// 2. The maximum length the array will ever be. +// 2. A SendProp describing what the elements are comprised of. +// 3. In the SendProp, you'll want to specify a proxy function so you can go grab the data from wherever it is. +// 4. A property name that matches the definition on the client. +// +#define SendPropVirtualArray( arrayLengthSendProxy, maxArrayLength, varTemplate, propertyName ) \ + varTemplate, \ + InternalSendPropArray( \ + maxArrayLength, \ + 0, \ + #propertyName, \ + arrayLengthSendProxy \ + ) + + +#define SendPropVariableLengthArray( arrayLengthSendProxy, varTemplate, arrayName ) \ + varTemplate, \ + InternalSendPropArray( \ + sizeof(((currentSendDTClass*)0)->arrayName) / PROPSIZEOF(currentSendDTClass, arrayName[0]), \ + PROPSIZEOF(currentSendDTClass, arrayName[0]), \ + #arrayName, \ + arrayLengthSendProxy \ + ) + +// Use this one to specify the element count and stride manually. +#define SendPropArray2( arrayLengthSendProxy, varTemplate, elementCount, elementStride, arrayName ) \ + varTemplate, \ + InternalSendPropArray( elementCount, elementStride, #arrayName, arrayLengthSendProxy ) + + + + +// Use these to create properties that exclude other properties. This is useful if you want to use most of +// a base class's datatable data, but you want to override some of its variables. +SendProp SendPropExclude( + const char *pDataTableName, // Data table name (given to BEGIN_SEND_TABLE and BEGIN_RECV_TABLE). + const char *pPropName // Name of the property to exclude. + ); + + +#endif // DATATABLE_SEND_H |