SendProp SendPropQuaternion( char *pVarName, int offset, 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<<nBits). SendVarProxyFn varProxy ) { SendProp ret; if(varProxy == SendProxy_QuaternionToQuaternion) { Assert(sizeofVar == sizeof(Quaternion)); } if ( nBits == 32 ) flags |= SPROP_NOSCALE; ret.m_Type = DPT_Quaternion; ret.m_pVarName = pVarName; ret.SetOffset( offset ); ret.m_nBits = nBits; ret.SetFlags( flags ); ret.m_fLowValue = fLowValue; ret.m_fHighValue = fHighValue; ret.m_fHighLowMul = AssignRangeMultiplier( ret.m_nBits, ret.m_fHighValue - ret.m_fLowValue ); ret.SetProxyFn( varProxy ); if( ret.GetFlags() & (SPROP_COORD | SPROP_NOSCALE | SPROP_NORMAL) ) ret.m_nBits = 0; return ret; }
void UTIL_DrawSendTable(FILE *fp, SendTable *pTable, int level = 1) { SendProp *pProp; const char *type; for (int i = 0; i < pTable->GetNumProps(); i++) { pProp = pTable->GetProp(i); if (pProp->GetDataTable()) { fprintf(fp, "%*sTable: %s (offset %d) (type %s)\n", level, "", pProp->GetName(), pProp->GetOffset(), pProp->GetDataTable()->GetName()); UTIL_DrawSendTable(fp, pProp->GetDataTable(), level + 1); } else { type = GetDTTypeName(pProp->GetType()); if (type != NULL) { fprintf(fp, "%*sMember: %s (offset %d) (type %s) (bits %d) (%s)\n", level, "", pProp->GetName(), pProp->GetOffset(), type, pProp->m_nBits, UTIL_SendFlagsToString(pProp->GetFlags(), pProp->GetType())); } else { fprintf(fp, "%*sMember: %s (offset %d) (type %d) (bits %d) (%s)\n", level, "", pProp->GetName(), pProp->GetOffset(), pProp->GetType(), pProp->m_nBits, UTIL_SendFlagsToString(pProp->GetFlags(), pProp->GetType())); } } } }
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<<nBits). SendVarProxyFn varProxy ) { SendProp ret; if ( varProxy == SendProxy_FloatToFloat ) { Assert( sizeofVar == 0 || sizeofVar == 4 ); } if ( nBits <= 0 || nBits == 32 ) { flags |= SPROP_NOSCALE; fLowValue = 0.f; fHighValue = 0.f; } else { if(fHighValue == HIGH_DEFAULT) fHighValue = (1 << nBits); if (flags & SPROP_ROUNDDOWN) fHighValue = fHighValue - ((fHighValue - fLowValue) / (1 << nBits)); else if (flags & SPROP_ROUNDUP) fLowValue = fLowValue + ((fHighValue - fLowValue) / (1 << nBits)); } ret.m_Type = DPT_Float; ret.m_pVarName = pVarName; ret.SetOffset( offset ); ret.m_nBits = nBits; ret.SetFlags( flags ); ret.m_fLowValue = fLowValue; ret.m_fHighValue = fHighValue; ret.m_fHighLowMul = AssignRangeMultiplier( ret.m_nBits, ret.m_fHighValue - ret.m_fLowValue ); ret.SetProxyFn( varProxy ); if( ret.GetFlags() & (SPROP_COORD | SPROP_NOSCALE | SPROP_NORMAL | SPROP_COORD_MP | SPROP_COORD_MP_LOWPRECISION | SPROP_COORD_MP_INTEGRAL ) ) ret.m_nBits = 0; return ret; }
static void SendTable_CalcNextVectorElems( SendTable *pTable ) { for ( int i=0; i < pTable->GetNumProps(); i++ ) { SendProp *pProp = pTable->GetProp( i ); if ( pProp->GetType() == DPT_DataTable ) { SendTable_CalcNextVectorElems( pProp->GetDataTable() ); } else if ( pProp->GetOffset() < 0 ) { pProp->SetOffset( -pProp->GetOffset() ); pProp->SetFlags( pProp->GetFlags() | SPROP_IS_A_VECTOR_ELEM ); } } }
void UTIL_DrawSendTable_XML(FILE *fp, SendTable *pTable, int space_count) { char spaces[255]; for (int i = 0; i < space_count; i++) { spaces[i] = ' '; } spaces[space_count] = '\0'; const char *type_name; SendTable *pOtherTable; SendProp *pProp; fprintf(fp, " %s<sendtable name=\"%s\">\n", spaces, pTable->GetName()); for (int i = 0; i < pTable->GetNumProps(); i++) { pProp = pTable->GetProp(i); fprintf(fp, " %s<property name=\"%s\">\n", spaces, pProp->GetName()); if ((type_name = GetDTTypeName(pProp->GetType())) != NULL) { fprintf(fp, " %s<type>%s</type>\n", spaces, type_name); } else { fprintf(fp, " %s<type>%d</type>\n", spaces, pProp->GetType()); } fprintf(fp, " %s<offset>%d</offset>\n", spaces, pProp->GetOffset()); fprintf(fp, " %s<bits>%d</bits>\n", spaces, pProp->m_nBits); fprintf(fp, " %s<flags>%s</flags>\n", spaces, UTIL_SendFlagsToString(pProp->GetFlags(), pProp->GetType())); if ((pOtherTable = pTable->GetProp(i)->GetDataTable()) != NULL) { UTIL_DrawSendTable_XML(fp, pOtherTable, space_count + 3); } fprintf(fp, " %s</property>\n", spaces); } fprintf(fp, " %s</sendtable>\n", spaces); }
// Spits out warnings for invalid properties and forces property values to // be in valid ranges for the encoders and decoders. static void SendTable_Validate( CSendTablePrecalc *pPrecalc ) { SendTable *pTable = pPrecalc->m_pSendTable; for( int i=0; i < pTable->m_nProps; i++ ) { SendProp *pProp = &pTable->m_pProps[i]; if ( pProp->GetArrayProp() ) { if ( pProp->GetArrayProp()->GetType() == DPT_DataTable ) { Error( "Invalid property: %s/%s (array of datatables) [on prop %d of %d (%s)].", pTable->m_pNetTableName, pProp->GetName(), i, pTable->m_nProps, pProp->GetArrayProp()->GetName() ); } } else { ErrorIfNot( pProp->GetNumElements() == 1, ("Prop %s/%s has an invalid element count for a non-array.", pTable->m_pNetTableName, pProp->GetName()) ); } // Check for 1-bit signed properties (their value doesn't get down to the client). if ( pProp->m_nBits == 1 && !(pProp->GetFlags() & SPROP_UNSIGNED) ) { DataTable_Warning("SendTable prop %s::%s is a 1-bit signed property. Use SPROP_UNSIGNED or the client will never receive a value.\n", pTable->m_pNetTableName, pProp->GetName()); } } for ( int i = 0; i < pPrecalc->GetNumProps(); ++i ) { const SendProp *pProp = pPrecalc->GetProp( i ); if ( pProp->GetFlags() & SPROP_ENCODED_AGAINST_TICKCOUNT ) { pTable->SetHasPropsEncodedAgainstTickcount( true ); break; } } }
SendProp SendPropInt( char *pVarName, int offset, int sizeofVar, int nBits, int flags, SendVarProxyFn varProxy ) { SendProp ret; if ( !varProxy ) { if ( sizeofVar == 1 ) { varProxy = SendProxy_Int8ToInt32; } else if ( sizeofVar == 2 ) { varProxy = SendProxy_Int16ToInt32; } else if ( sizeofVar == 4 ) { varProxy = SendProxy_Int32ToInt32; } else { Assert(!"SendPropInt var has invalid size"); varProxy = SendProxy_Int8ToInt32; // safest one... } } // Figure out # of bits if the want us to. if ( nBits <= 0 ) { Assert( sizeofVar == 1 || sizeofVar == 2 || sizeofVar == 4 ); nBits = sizeofVar * 8; } ret.m_Type = DPT_Int; ret.m_pVarName = pVarName; ret.SetOffset( offset ); ret.m_nBits = nBits; ret.SetFlags( flags ); // Use UInt proxies if they want unsigned data. This isn't necessary to encode // the values correctly, but it lets us check the ranges of the data to make sure // they're valid. ret.SetProxyFn( varProxy ); if( ret.GetFlags() & SPROP_UNSIGNED ) { if( varProxy == SendProxy_Int8ToInt32 ) ret.SetProxyFn( SendProxy_UInt8ToInt32 ); else if( varProxy == SendProxy_Int16ToInt32 ) ret.SetProxyFn( SendProxy_UInt16ToInt32 ); else if( varProxy == SendProxy_Int32ToInt32 ) ret.SetProxyFn( SendProxy_UInt32ToInt32 ); } return ret; }