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.
808 lines
26 KiB
808 lines
26 KiB
//========= 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
|
|
|