//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //=============================================================================// #include "dt_send.h" #include "mathlib/mathlib.h" #include "mathlib/vector.h" #include "tier0/dbg.h" #include "dt_utlvector_common.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" #if !defined(_STATIC_LINKED) || defined(GAME_DLL) static CNonModifiedPointerProxy *s_pNonModifiedPointerProxyHead = NULL; void SendProxy_UInt8ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); void SendProxy_UInt16ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); void SendProxy_UInt32ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); #ifdef SUPPORTS_INT64 void SendProxy_UInt64ToInt64( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID); #endif CNonModifiedPointerProxy::CNonModifiedPointerProxy( SendTableProxyFn fn ) { m_pNext = s_pNonModifiedPointerProxyHead; s_pNonModifiedPointerProxyHead = this; m_Fn = fn; } CStandardSendProxiesV1::CStandardSendProxiesV1() { m_Int8ToInt32 = SendProxy_Int8ToInt32; m_Int16ToInt32 = SendProxy_Int16ToInt32; m_Int32ToInt32 = SendProxy_Int32ToInt32; #ifdef SUPPORTS_INT64 m_Int64ToInt64 = SendProxy_Int64ToInt64; #endif m_UInt8ToInt32 = SendProxy_UInt8ToInt32; m_UInt16ToInt32 = SendProxy_UInt16ToInt32; m_UInt32ToInt32 = SendProxy_UInt32ToInt32; #ifdef SUPPORTS_INT64 m_UInt64ToInt64 = SendProxy_UInt64ToInt64; #endif m_FloatToFloat = SendProxy_FloatToFloat; m_VectorToVector = SendProxy_VectorToVector; } CStandardSendProxies::CStandardSendProxies() { m_DataTableToDataTable = SendProxy_DataTableToDataTable; m_SendLocalDataTable = SendProxy_SendLocalDataTable; m_ppNonModifiedPointerProxies = &s_pNonModifiedPointerProxyHead; } CStandardSendProxies g_StandardSendProxies; // ---------------------------------------------------------------------- // // Proxies. // ---------------------------------------------------------------------- // void SendProxy_AngleToFloat( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { float angle; angle = *((float*)pData); pOut->m_Float = anglemod( angle ); Assert( IsFinite( pOut->m_Float ) ); } void SendProxy_FloatToFloat( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { pOut->m_Float = *((float*)pData); Assert( IsFinite( pOut->m_Float ) ); } void SendProxy_QAngles( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ) { QAngle *v = (QAngle*)pData; pOut->m_Vector[0] = anglemod( v->x ); pOut->m_Vector[1] = anglemod( v->y ); pOut->m_Vector[2] = anglemod( v->z ); } void SendProxy_VectorToVector( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { Vector& v = *(Vector*)pData; Assert( v.IsValid() ); pOut->m_Vector[0] = v[0]; pOut->m_Vector[1] = v[1]; pOut->m_Vector[2] = v[2]; } void SendProxy_VectorXYToVectorXY( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { Vector& v = *(Vector*)pData; Assert( v.IsValid() ); pOut->m_Vector[0] = v[0]; pOut->m_Vector[1] = v[1]; } #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) { Quaternion& q = *(Quaternion*)pData; Assert( q.IsValid() ); pOut->m_Vector[0] = q[0]; pOut->m_Vector[1] = q[1]; pOut->m_Vector[2] = q[2]; pOut->m_Vector[3] = q[3]; } #endif void SendProxy_Int8ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { pOut->m_Int = *((const char*)pData); } void SendProxy_Int16ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { pOut->m_Int = *((short*)pData); } void SendProxy_Int32ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { pOut->m_Int = *((int*)pData); } #ifdef SUPPORTS_INT64 void SendProxy_Int64ToInt64( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { pOut->m_Int64 = *((int64*)pData); } #endif void SendProxy_UInt8ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { pOut->m_Int = *((const unsigned char*)pData); } void SendProxy_UInt16ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { pOut->m_Int = *((unsigned short*)pData); } void SendProxy_UInt32ToInt32( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { *((unsigned long*)&pOut->m_Int) = *((unsigned long*)pData); } #ifdef SUPPORTS_INT64 void SendProxy_UInt64ToInt64( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { *((int64*)&pOut->m_Int64) = *((uint64*)pData); } #endif void SendProxy_StringToString( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { pOut->m_pString = (const char*)pData; } void* SendProxy_DataTableToDataTable( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) { return (void*)pData; } void* SendProxy_DataTablePtrToDataTable( const SendProp *pProp, const void *pStructBase, const void *pData, CSendProxyRecipients *pRecipients, int objectID ) { return *((void**)pData); } static void SendProxy_Empty( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID) { } //----------------------------------------------------------------------------- // Purpose: If the recipient is the same as objectID, go ahead and iterate down // the m_Local stuff, otherwise, act like it wasn't there at all. // This way, only the local player receives information about him/herself. // Input : *pVarData - // *pOut - // objectID - //----------------------------------------------------------------------------- void* SendProxy_SendLocalDataTable( const SendProp *pProp, const void *pStruct, const void *pVarData, CSendProxyRecipients *pRecipients, int objectID ) { pRecipients->SetOnly( objectID - 1 ); return ( void * )pVarData; } // ---------------------------------------------------------------------- // // Prop setup functions (for building tables). // ---------------------------------------------------------------------- // float AssignRangeMultiplier( int nBits, double range ) { unsigned long iHighValue; if ( nBits == 32 ) iHighValue = 0xFFFFFFFE; else iHighValue = ((1 << (unsigned long)nBits) - 1); float fHighLowMul = iHighValue / range; if ( CloseEnough( range, 0 ) ) fHighLowMul = iHighValue; // If the precision is messing us up, then adjust it so it won't. if ( (unsigned long)(fHighLowMul * range) > iHighValue || (fHighLowMul * range) > (double)iHighValue ) { // Squeeze it down smaller and smaller until it's going to produce an integer // in the valid range when given the highest value. float multipliers[] = { 0.9999, 0.99, 0.9, 0.8, 0.7 }; int i; for ( i=0; i < ARRAYSIZE( multipliers ); i++ ) { fHighLowMul = (float)( iHighValue / range ) * multipliers[i]; if ( (unsigned long)(fHighLowMul * range) > iHighValue || (fHighLowMul * range) > (double)iHighValue ) { } else { break; } } if ( i == ARRAYSIZE( multipliers ) ) { // Doh! We seem to be unable to represent this range. Assert( false ); return 0; } } return fHighLowMul; } SendProp SendPropFloat( const char *pVarName, // Variable name. int offset, // Offset into container structure. int sizeofVar, int nBits, // Number of bits to use when encoding. int flags, float fLowValue, // For floating point, low and high values. float fHighValue, // High value. If HIGH_DEFAULT, it's (1<